UMAP projections
Cell clusters
# srt <- readRDS("/labs/khatrilab/hongzheng/webapps/isb/srt_isb260.meta.rds")
srt <- readRDS(here("data/isb/isb_sc_metadata.RDS"))
cells <- c("CD14 Monocyte", "CD4 T", "CD8 T", "NK", "B", "CD16 Monocyte", "cDC", "pDC")
srt <- srt %>% select(sample, sampleID, cell, celltype, severity, UMAP_1, UMAP_2) %>%
filter(celltype %in% cells)
# ggplot theme to overlay cluster id #s on UMAP
gg_srt_relabel <- function(df, x_var, y_var, color_var, cell_fraction = 1){
plt <- df %>%
ggplot(aes(x = !!sym(x_var), y = !!sym(y_var), color = !!sym(color_var))) +
geom_point(size = 0.5, alpha = 0.5)+
theme_bw() +
scale_color_brewer(palette = "Dark2")+
guides(color = guide_legend(override.aes = list(size = 2, alpha = 1)))
g <- ggplot_build(plt)
plt_ids <- g$data[[1]]
group_levels <- levels(factor(g$plot$data[[g$plot$labels$colour]]))
plt_key <- g$data[[1]] %>%
select(colour, group) %>%
distinct() %>%
mutate(label = map_chr(group, function(x) group_levels[x])) %>%
mutate(label = factor(label, level = group_levels)) %>%
mutate(label = sprintf("%s) %s", 1:n(), label)) %>%
select(-group)
plt_df <- plt_ids %>%
left_join(plt_key, by = "colour")
plt_center <- plt_df %>%
group_by(label) %>% summarise(x = mean(x), y = mean(y)) %>%
mutate(label = gsub(").*","",label))
plt_repel <- plt_df %>%
ggplot(aes(x=x,y=y,color=label)) +
geom_point(size = 0.5)+
ggrepel::geom_text_repel(data=plt_center,
aes(label=label, bg.color="white", bg.r=0.25),
color = "black",
fontface = "bold") +
theme_bw() +
guides(color = guide_legend(override.aes = list(size = 2) ) ) +
labs(x=x_var, y = y_var, color = color_var) +
theme(axis.text = element_blank(), axis.ticks = element_blank())
return(plt_repel)
}
plt_srt <- srt %>%
filter(celltype %in% cells) %>%
filter(sampleID == "INCOV069-BL") %>%
gg_srt_relabel(x_var = "UMAP_1", y_var = "UMAP_2", color_var = "celltype", cell_fraction = 0.1) +
scale_color_brewer(palette = "Dark2")+
theme(axis.text = element_blank(), axis.ticks = element_blank()) +
labs(x="UMAP 1", y = "UMAP 2", color = "Cell Cluster")
plt_srt

Allele frequency
# samp <- "INCOV069-BL"
# samp <- "INCOV022-BL"
# samp <- "INCOV083-BL"
samp <- "INCOV028-BL"
scHLAcount_dir <- sprintf("%s/scHLAcount", isb_path)
# Create tibble of all genotyper and sample combinations
allele_data <- expand_grid(
genotyper = c("invitro", "arcasHLA", "optitype", "phlat", "hlaminer"),
sample = read_lines(here("data/isb/scHLAcount/BL_fastq_files.txt"))) %>%
filter(grepl(samp, sample)) %>%
# Import data based on sample and genotyper
mutate(result_path = sprintf("%s/scHLAcount/output/%s",isb_path, genotyper),
barcode_path = sprintf("%s/scHLAcount/barcodes", isb_path)) %>%
mutate(data = pmap(list(sample, result_path, barcode_path), function(s,r,b){
df <- scHLA_data_processing(
sample=s,
result_dir=r,
barcode_dir=b
)
})) %>% unnest(data)
plot_allele_frequencies <- function(allele_data, gene_select){
allele_data_ratios <- allele_data %>%
filter(gene == gene_select) %>%
mutate(genotyper = reformat_hla_genotyper(genotyper)) %>%
mutate(allele_order = fct_recode(factor(allele_order), "Allele 1" = "1", "Allele 2" = "2"))
allele_label <- allele_data_ratios %>%
select(genotyper, allele_order, allele) %>%
distinct()
plt <- srt %>%
left_join(allele_data_ratios %>% filter(gene == gene_select), by = "cell") %>%
filter(!is.na(allele)) %>%
ggplot(aes(x = UMAP_1, y = UMAP_2, color = allele_ratio)) +
geom_point(size = 0.5, alpha = 0.5)+
theme_bw() +
facet_grid(allele_order~genotyper)+
scale_color_gradient2(high = "red", mid = "grey80", low = "blue", midpoint = 0.5, na.value = "transparent") +
labs(x="UMAP 1", y="UMAP 2", color = "Allele \nFrequency")+
theme(axis.ticks = element_blank(), axis.text = element_blank())+
coord_cartesian(ylim = c(-10,15))
plt_allele_freq <- plt+
geom_label(data = allele_label, aes(x=-10,y=14, color = NULL, label = allele), size = 3, hjust = 0)
return(plt_allele_freq)
}
plt_allele_freq <- plot_allele_frequencies(allele_data = allele_data, gene_select = "A")
plt_allele_freq

plot_allele_frequencies(allele_data = allele_data, gene_select = "DRB1")

Maximum allele
plot_allele_ratios <- function(allele_data, gene_select){
# Create tibble of all genotyper and sample combinations
allele_max_ratio <- allele_data %>%
select(genotyper, cell, gene, allele_order, allele_ratio) %>%
# group_by(genotyper, cell, allele_order) %>% mutate(test = length(allele_order))
pivot_wider(names_from = "allele_order", values_from = "allele_ratio", names_prefix = "allele_") %>%
rowwise() %>%
mutate(max_ratio = max(across(contains("allele_")), na.rm = T)) %>%
select(genotyper, cell, gene, max_ratio) %>%
filter(gene == gene_select)
allele_label <- allele_data %>% select(sample, genotyper, gene, allele) %>%
filter(gene == gene_select) %>%
separate(sample, into = c("sample", NULL), sep = "_", extra = "drop") %>%
distinct() %>%
group_by(sample, genotyper, gene) %>% nest() %>% unnest_wider(data) %>%
mutate(genotyper = reformat_hla_genotyper(genotyper)) %>%
mutate(allele = map_chr(allele, paste, collapse = "\n"))
plt_max_allele <- srt %>%
left_join(allele_max_ratio %>% filter(gene == gene_select), by = "cell") %>%
# mutate(genotyper = fct_relevel(genotyper, "invitro")) %>%
mutate(genotyper = reformat_hla_genotyper(genotyper)) %>%
filter(!is.na(genotyper)) %>%
ggplot(aes(x = UMAP_1, y = UMAP_2, color = max_ratio)) +
geom_point(size = 0.5, alpha = 0.5)+
geom_label(data = allele_label, aes(color = NULL, label = allele, x = -Inf, y = -Inf),
hjust = -0.1, vjust = -0.1, size = 3, hjust = 0) +
theme_bw() +
facet_grid(.~genotyper)+
scale_color_gradient(high = "red", low = "blue", na.value = "transparent") +
labs(x="UMAP 1", y="UMAP 2", color = "Maximum Allele \nFrequency")+
theme(axis.ticks = element_blank(), axis.text = element_blank())
return(plt_max_allele)
}
plt_max_allele <- plot_allele_ratios(allele_data = allele_data, gene_select = "A")
plt_max_allele

plot_allele_ratios(allele_data = allele_data, gene_select = "DRB1")

allele_max_ratio <- allele_data %>%
filter(genotyper == "invitro") %>%
select(cell, gene, allele_order, allele_ratio) %>%
pivot_wider(names_from = "allele_order", values_from = "allele_ratio", names_prefix = "allele_") %>%
rowwise() %>%
mutate(max_ratio = max(across(contains("allele_")), na.rm = T)) %>%
select(cell, gene, max_ratio)
allele_label <- allele_data %>%
filter(genotyper == "invitro") %>%
select(sample, gene, allele) %>%
separate(sample, into = c("sample", NULL), sep = "_", extra = "drop") %>%
distinct() %>%
group_by(sample, gene) %>% nest() %>% unnest_wider(data) %>%
mutate(allele = map_chr(allele, paste, collapse = "\n"))
srt %>%
left_join(allele_max_ratio, by = "cell") %>%
# mutate(genotyper = fct_relevel(genotyper, "invitro")) %>%
filter(!is.na(max_ratio)) %>%
ggplot(aes(x = UMAP_1, y = UMAP_2, color = max_ratio)) +
geom_point(size = 0.5, alpha = 0.5)+
geom_label(data = allele_label, aes(color = NULL, label = allele, x = -Inf, y = -Inf),
hjust = -0.1, vjust = -0.1, size = 3, hjust = 0) +
theme_bw() +
facet_grid(.~gene)+
scale_color_gradient(high = "red", low = "blue", na.value = "transparent") +
labs(x="UMAP 1", y="UMAP 2", color = "Maximum Allele \nFrequency")+
theme(axis.ticks = element_blank(), axis.text = element_blank())

allele_max_ratio <- allele_data %>%
select(genotyper, cell, gene, allele_order, allele_ratio) %>%
# group_by(genotyper, cell, allele_order) %>% mutate(test = length(allele_order))
pivot_wider(names_from = "allele_order", values_from = "allele_ratio", names_prefix = "allele_") %>%
rowwise() %>%
mutate(max_ratio = max(across(contains("allele_")), na.rm = T)) %>%
select(genotyper, cell, gene, max_ratio)
allele_label <- allele_data %>% select(sample, genotyper, gene, allele) %>%
separate(sample, into = c("sample", NULL), sep = "_", extra = "drop") %>%
distinct() %>%
group_by(sample, genotyper, gene) %>% nest() %>% unnest_wider(data) %>%
mutate(genotyper = reformat_hla_genotyper(genotyper)) %>%
mutate(allele = map_chr(allele, paste, collapse = "\n"))
plt_max_allele_allGenesTypers <- srt %>%
left_join(allele_max_ratio, by = c("cell")) %>%
# mutate(genotyper = fct_relevel(genotyper, "invitro")) %>%
mutate(genotyper = reformat_hla_genotyper(genotyper)) %>%
filter(!is.na(max_ratio)) %>%
ggplot(aes(x = UMAP_1, y = UMAP_2, color = max_ratio)) +
rasterise(geom_point(size = 0.5, alpha = 0.5), dpi = 300)+
geom_label(data = allele_label, aes(color = NULL, label = allele, x = -Inf, y = -Inf),
hjust = -0.1, vjust = -0.1, size = 3, hjust = 0) +
theme_bw() +
facet_grid(genotyper~gene)+
scale_color_gradient(high = "red", low = "blue", na.value = "transparent") +
labs(x="UMAP 1", y="UMAP 2", color = "Maximum Allele \nFrequency")+
theme(axis.ticks = element_blank(), axis.text = element_blank())
plt_max_allele_allGenesTypers

Meta-analysis approach
Rationale
- Goal: determine a summary statistic for allele ratio across all
cells
- Problem:
- Each cell in scRNA experiment has its own ratio of HLA allele 1
reads : HLA allele 2 reads
- A wide range of total read counts may go into each cell’s ratio
- Small difference in read counts for cells with low total reads can
greatly alter the allele ratio compared to cells with high total read
counts
- I.e. Cells with low read counts are more likely to have imprecise
allele ratios
- Simply averaging ratios would equally weight high confidence, high
read count ratios with low confidence, low read ratios
- Approach
- Meta-analysis methods specifically address type of problem,
typically by weighing an effect by the inverse of its variance
- In the setting of ratios, basic approach would be to combine
log-odds ratio of alleles, weighted by inverse variance
- Would use a random effects model because do not expect each cell in
a group would have the same exact ratio due to various stochastic
transcriptional effects
Calculating summary effect sizes
- Analysis can take some time, so run on an HPC cluster using
slurm
- Contained in a separate script
sc_meta.R:
Contents of sc_meta.R
library(tidyverse)
library(meta)
source(here("helper_functions/data_import_functions.R"))
isb_path <- here("data/isb")
srt <- readRDS(here("data/isb/isb_sc_metadata.RDS"))
cells <- c("CD14 Monocyte", "CD4 T", "CD8 T", "NK", "B", "CD16 Monocyte", "cDC", "pDC")
srt <- srt %>% select(sample, sampleID, cell, celltype, severity, UMAP_1, UMAP_2) %>%
filter(celltype %in% cells)
# Function to perform meta-analysis on dataframe where
# each row is a cell and columns:
# `observed` (reads of dominant allele)
# `gene_sum_typed` (total cell reads)
# `expected` (reads of one allele expected if 50:50 allele_1 : allele_2)
sc_meta <- function(df){
l <- nrow(df)
m <- metabin(event.e = observed, n.e = gene_sum_typed, event.c = expected, n.c = gene_sum_typed,
data = df,
method = "Inverse",
incr = 0.1,
sm = "OR")
data.frame(summary(m)$random) %>%
mutate(n_cells = l) %>%
select(TE, seTE, lower, upper, n_cells)
}
# Import data based on sample and genotyper
cell_stats <- expand_grid(
genotyper = c("invitro", "arcasHLA", "optitype", "phlat", "hlaminer"),
sample = read_lines(here("data/isb/scHLAcount/BL_fastq_files.txt"))) %>%
# head(5) %>% # Specify limit to number of meta-analyses
mutate(data = map2(sample, genotyper, function(s,g){
result_path = sprintf("%s/scHLAcount/output_ase/%s",isb_path, g)
barcode_path = sprintf("%s/scHLAcount/barcodes", isb_path)
scHLA_data_processing(sample = s,
result_dir = result_path,
barcode_dir = barcode_path)
})) %>% unnest(data) %>%
filter(!is.na(cell)) %>%
mutate(sample = gsub("_[A-Z][0-9]$","",sample)) %>% # Consolidate samples
left_join(srt %>% select(celltype, cell), by = "cell") %>% # Add celltypes
filter(celltype %in% cells) # Keep only standard cell types
meta_df <- cell_stats %>%
# Keep only most expressed allele (or random if 50:50)
group_by(sample, genotyper, gene, cell) %>%
slice_max(order_by = allele_ratio, n = 1, with_ties = F) %>%
ungroup() %>%
# Fill out contingency table
mutate(complement = gene_sum_typed - count,
expected = 0.5*gene_sum_typed) %>%
rename(observed = count) %>%
select(sample, genotyper, celltype, gene, observed, expected, gene_sum_typed) %>%
group_by(sample, genotyper, celltype, gene) %>%
# Nest and run meta-analysis
nest() %>%
ungroup() %>%
mutate(data = map(data,function(x) {sc_meta(x)})) %>%
unnest(data)
write_csv(meta_df, here("7_HLA_ASE/meta_analysis_results_12.csv"))
Single sample analysis
meta_df <- read_csv(here("7_HLA_ASE/meta_analysis_results_c12.csv"))
Rows: 16440 Columns: 9
── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (4): sample, genotyper, celltype, gene
dbl (5): TE, seTE, lower, upper, n_cells
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
meta_df
plot_meta_odds <- function(df, cell_type, locus){
df %>%
filter(celltype == cell_type, gene == locus) %>%
mutate(genotyper = reformat_hla_genotyper(genotyper)) %>%
ggplot(aes(x = genotyper, y = TE, ymin = lower, ymax = upper))+
geom_point()+
geom_errorbar(width = 0.4)+
theme_bw()+
scale_y_continuous(limits = c(0,NA))+
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
labs(y = "Log-Odds ratio of dominant allele", x= NULL)
}
plt_meta <- meta_df %>%
filter(sample == samp) %>%
plot_meta_odds(cell_type = "cDC", locus = "A")
plt_meta

meta_df %>%
filter(sample == samp) %>%
plot_meta_odds(cell_type = "cDC", locus = "DRB1")

samples <- unique(meta_df$sample)
for (i in 1:length(samples)){
plt_meta <- meta_df %>%
filter(sample == samples[i]) %>%
plot_meta_odds(cell_type = "CD14 Monocyte", locus = "A") +
ggtitle(samples[i])
print(plt_meta)
}
































































plt_meta_allLoci <- meta_df %>%
filter(sample == samp) %>%
filter(celltype == "cDC") %>%
mutate(genotyper = reformat_hla_genotyper(genotyper)) %>%
ggplot(aes(x = genotyper, y = TE, ymin = lower, ymax = upper))+
geom_point()+
geom_errorbar(width = 0.4)+
facet_grid(.~gene)+
theme_bw()+
scale_y_continuous(limits = c(0,NA))+
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
labs(y = "Log-Odds ratio\nof dominant allele", x= NULL)
plt_meta_allLoci

Multi-sample analysis
meta_df <- read_csv(here("7_HLA_ASE/meta_analysis_results_c12.csv")) %>%
mutate(genotyper = reformat_hla_genotyper(genotyper),
celltype = factor(celltype, levels = c(
"cDC", "CD14 Monocyte", "B", "pDC", "CD16 Monocyte", "CD8 T", "CD4 T", "NK")))
Rows: 16440 Columns: 9
── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (4): sample, genotyper, celltype, gene
dbl (5): TE, seTE, lower, upper, n_cells
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
meta_df %>%
ggplot(aes(x=celltype,y=TE, fill = celltype))+
geom_violin()+
geom_jitter(alpha = 0.2, size = 0.2)+
stat_summary(fun=mean, stat= "point")+
stat_summary(fun.data = mean_se, geom="errorbar")+
facet_grid(gene~genotyper)+
theme_bw()+
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
labs(y = "Log-Odds ratio of dominant allele", x= NULL, fill = "Cell type") +
scale_fill_brewer(palette = "Dark2")

meta_df %>%
ggplot(aes(x=genotyper,y=TE, fill = celltype))+
geom_violin()+
geom_jitter(alpha = 0.2, size = 0.2)+
stat_summary(fun=mean, stat= "point")+
stat_summary(fun.data = mean_se, geom="errorbar")+
facet_grid(gene~celltype)+
theme_bw()+
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
labs(y = "Log-Odds ratio of dominant allele", x= NULL, fill = "Cell type") +
scale_fill_brewer(palette = "Dark2")

meta_df %>%
filter(sample == samp) %>%
filter(celltype == "cDC") %>%
mutate(genotyper = reformat_hla_genotyper(genotyper)) %>%
ggplot(aes(x = genotyper, y = TE, ymin = lower, ymax = upper))+
geom_point()+
geom_errorbar(width = 0.4)+
facet_grid(.~gene)+
theme_bw()+
scale_y_continuous(limits = c(0,NA))+
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
labs(y = "Log-Odds ratio\nof dominant allele", x= NULL)
Correlation analysis
meta_df %>%
filter(gene == "A", celltype == "cDC") %>%
select(sample, genotyper, TE) %>%
pivot_wider(names_from = "genotyper", values_from = "TE") %>%
select(-sample) %>%
GGally::ggpairs(progress = FALSE) +
theme_bw()

accuracy_df <- readRDS(here("3_DRB/isb_accuracy_drb345_filtered.RDS")) %>%
mutate(genotyper = reformat_hla_genotyper(genotyper)) %>%
select(sample, gene=locus, genotyper, accuracy) %>%
distinct()
for (i in c(0,1)){
suppressWarnings({
plt <- meta_df %>%
ungroup() %>%
filter(gene == "A", celltype == "cDC") %>%
left_join(accuracy_df, by = c("sample", "gene", "genotyper")) %>%
filter(accuracy == i | genotyper == "Ground truth") %>%
# drop_na(accuracy) %>%
select(sample, genotyper, TE) %>%
pivot_wider(names_from = "genotyper", values_from = "TE") %>%
select(-sample) %>%
GGally::ggpairs(progress = FALSE) +
theme_bw() +
ggtitle(sprintf("Correlation of allele ratios where accuracy = %s", i))
print(plt)
})
}


corr_df <- meta_df %>%
mutate(genotyper = reformat_hla_genotyper(genotyper)) %>%
select(sample, genotyper, celltype, gene, TE) %>%
pivot_wider(names_from = "genotyper", values_from = "TE") %>%
pivot_longer(c(arcasHLA, HLAminer, OptiType, PHLAT), names_to = "genotyper", values_to = "TE") %>%
mutate(genotyper = reformat_hla_genotyper(genotyper))
corr_df %>%
ggplot(aes(x=`Ground truth`, y=TE))+
geom_point(size = 0.5)+
facet_grid(gene ~ genotyper) +
theme_bw() +
ggpubr::stat_cor(aes(label = ..rr.label..), label.x.npc = "left", label.y.npc = "top", geom = "label")

for (i in c(0,1)){
suppressWarnings({
plt <- corr_df %>%
ungroup() %>%
# filter(gene == "A", celltype == "cDC") %>%
left_join(accuracy_df, by = c("sample", "gene", "genotyper")) %>%
filter(accuracy == i) %>%
ggplot(aes(x=`Ground truth`, y=TE))+
geom_point(size = 0.5)+
facet_grid(gene ~ genotyper) +
theme_bw() +
ggpubr::stat_cor(aes(label = ..rr.label..), label.x.npc = "left", label.y.npc = "top", geom = "label") +
ggtitle(sprintf("Correlation of allele ratios where accuracy = %s", i)) +
labs(y = "Predicted genotype HLA allele log-odds ratio", x = "Ground truth genotype HLA allele log-odds ratio")
assign(sprintf("plt_meta_corr_%s", i), plt)
print(plt)
})
}


plt_meta_corr_abbrev <- corr_df %>%
left_join(accuracy_df, by = c("sample", "gene", "genotyper")) %>%
filter(gene == "A", accuracy %in% c(0,0.5,1)) %>%
ggplot(aes(x=`Ground truth`, y=TE))+
geom_point(size = 0.5)+
facet_grid(accuracy ~ genotyper, labeller = labeller(accuracy = function(x) sprintf("Accuracy: %s", x))) +
theme_bw() +
ggpubr::stat_cor(aes(label = ..rr.label..), label.x.npc = "left", label.y.npc = "top", geom = "label", method = "pearson") +
labs(y = "Log-odds ratio using predicted genotype", x = "Log-odds ratio using ground truth genotyper")
plt_meta_corr_abbrev
Warning: Removed 186 rows containing non-finite values (stat_cor).
Warning: Removed 186 rows containing missing values (geom_point).

accuracy_df %>%
ungroup() %>%
drop_na() %>%
count(gene, genotyper, accuracy)
By severity
meta_df %>%
filter(genotyper == "Ground truth") %>%
left_join(
srt %>%
select(sample = sampleID, severity) %>%
distinct(),
by = "sample"
) %>%
ggplot(aes(x=severity,y=TE, fill = celltype))+
geom_violin()+
geom_jitter(alpha = 0.2, size = 0.2)+
stat_summary(fun=mean, stat= "point")+
stat_summary(fun.data = mean_se, geom="errorbar")+
facet_grid(gene~celltype)+
theme_bw()+
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
labs(y = "Log-Odds ratio of dominant allele", x= NULL, fill = "Cell type") +
scale_fill_brewer(palette = "Dark2")

meta_df %>%
filter(genotyper == "Ground truth") %>%
left_join(
srt %>%
select(sample = sampleID, severity) %>%
distinct(),
by = "sample"
) %>%
mutate(severity = as.numeric(severity)) %>%
ggplot(aes(x = severity, y = TE)) +
# geom_point() +
stat_summary(fun=mean, stat= "point", size = 0.2)+
stat_summary(fun.data = mean_se, geom="errorbar", size = 0.2)+
stat_smooth(method = "lm")+
facet_grid(celltype~gene)+
theme_bw()
`geom_smooth()` using formula 'y ~ x'

Assemble plot
# plt_allele_freq_lgd <- cowplot::get_legend(plt_allele_freq)
# plt_max_allele_lgd <- cowplot::get_legend(plt_max_allele)
col_1 <- plot_grid(
plt_allele_freq,
plt_max_allele,
ncol = 1,
rel_heights = c(5,3),
align = "v", axis = "lr",
labels = LETTERS[1:2]
)
col_2 <- plot_grid(
plt_srt,
plt_meta,
ncol = 1,
align = "v", axis = "lr",
labels = LETTERS[3:4],
hjust = 0.5
)
row_1 <- plot_grid(
col_1,
col_2,
nrow = 1,
rel_widths = c(6,3)
)
row_2 <- plot_grid(
plt_meta_corr_0 +ggtitle(NULL),
plt_meta_corr_1 +ggtitle(NULL),
labels = LETTERS[5:6],
ncol = 2
)
Warning: Removed 4064 rows containing non-finite values (stat_cor).
Warning: Removed 4064 rows containing missing values (geom_point).
Warning: Removed 109 rows containing non-finite values (stat_cor).
Warning: Removed 109 rows containing missing values (geom_point).
plot_grid(
row_1,
row_2,
rel_heights = c(3,2),
ncol = 1
)

col_1 <- plot_grid(
plt_srt,
plt_meta,
ncol = 1,
align = "v", axis = "lr",
labels = LETTERS[c(1,3)],
label_x = -0.05
)
col_2 <- plot_grid(
plt_max_allele,
plt_meta_corr_abbrev,
ncol = 1,
rel_heights = c(3,5),
align = "v", axis = "lr",
labels = LETTERS[c(2,4)],
label_x = -0.05
)
Warning: Removed 186 rows containing non-finite values (stat_cor).
Warning: Removed 186 rows containing missing values (geom_point).
plt_fig_main <- plot_grid(
NULL,
col_1,
col_2,
nrow = 1,
rel_widths = c(0.25,3,6)
)
plt_fig_main

col_1 <- plot_grid(
plt_srt,
plt_meta+ labs(y="Log-odds ratio\nof dominant allele"),
ncol = 1,
align = "v", axis = "lr",
labels = LETTERS[c(1,3)],
label_x = -0.05
)
col_2 <- plot_grid(
plt_max_allele,
plt_meta_corr_abbrev + facet_grid(. ~ genotyper) + labs(y="Log-odds ratio using\npredicted genotype"),
ncol = 1,
rel_heights = c(1,1),
align = "v", axis = "lr",
labels = LETTERS[c(2,4)],
label_x = -0.05
)
Warning: Removed 186 rows containing non-finite values (stat_cor).
Warning: Removed 186 rows containing missing values (geom_point).
plt_fig_main <- plot_grid(
NULL,
col_1,
NULL,
col_2,
nrow = 1,
rel_widths = c(0.25,3,0.25,6)
)
plt_fig_main

save_plot(here("figures_pdf/v2/7_scHLA.pdf"), plt_fig_main, base_height = 5, base_width = 14)
plt_fig_supp <- plt_meta_corr_abbrev + facet_grid(accuracy ~ genotyper, margins = "accuracy")
plt_fig_supp
Warning: Removed 372 rows containing non-finite values (stat_cor).
Warning: Removed 372 rows containing missing values (geom_point).

save_plot(here("figures_pdf/v2/s8_ASE_correlation.pdf"), plt_fig_supp, base_height = 5, base_width = 6)
Warning: Removed 372 rows containing non-finite values (stat_cor).
Warning: Removed 372 rows containing missing values (geom_point).
plt_fig_supp_allLoci <- plot_grid(
plt_max_allele_allGenesTypers,
plt_meta_allLoci,
ncol = 1,
rel_heights = c(0.8,0.2),
align = "v",
axis = "lr",
labels = LETTERS[1:2]
)
plt_fig_supp_allLoci

save_plot(here("figures_pdf/v2/s7_ASE_allLoci.pdf"), plt_fig_supp_allLoci, base_height = 10, base_width = 12)
LS0tCnRpdGxlOiAiNykgRWZmZWN0IG9mIGdlbm90eXBlcnMgb24gSExBIGFsbGVsZS1zcGVjaWZpYyBleHByZXNzaW9uIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKLS0tCgojIFNldHVwCmBgYHtyLCBtZXNzYWdlID0gRn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkobWV0YSkKbGlicmFyeShjb3dwbG90KQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkoZ2dyYXN0cikKCnNvdXJjZShoZXJlKCJoZWxwZXJfZnVuY3Rpb25zL2RhdGFfaW1wb3J0X2Z1bmN0aW9ucy5SIikpCnNvdXJjZShoZXJlKCJoZWxwZXJfZnVuY3Rpb25zL2ZpZ3VyZV9mb3JtYXRfZnVuY3Rpb25zLlIiKSkKc291cmNlKGhlcmUoImhlbHBlcl9mdW5jdGlvbnMvY2FsY3VsYXRpb25fZnVuY3Rpb25zLlIiKSkKYWxsX2hsYV9leHBhbmRlZCA8LSByZWFkUkRTKGhlcmUoIjJfYWNjdXJhY3kvYWxsX2hsYV9leHBhbmRlZC5SRFMiKSkKaXNiX3BhdGggPC0gaGVyZSgiZGF0YS9pc2IiKQpgYGAKCgojIFJ1bm5pbmcgc2NITEEgY291bnQKCi0gKipOT1RFOioqIEZpbGVwYXRocyBmb3IgcnVubmluZyBzY0hMQWNvdW50IG9uIHJhdyBzZXF1ZW5jaW5nIGRhdGEgaGF2ZSBub3QgYmVlbiByZWZhY3RvcmVkIGZvciBnaXRodWIgcmVwby4gQWxsIG91dHB1dCBmaWxlcyByZWxldmFudCBmb3IgZG93bnN0cmVhbSBhbmFseXNpcyBoYXZlIGJlZW4gbW92ZWQgdG8gYGRhdGEvaXNiL3NjSExBY291bnRgIHdpdGhpbiB0aGUgZ2l0aHViIHJlcG8uICAKCiMjIyBQcmVwYXJlIHJlZmVyZW5jZSBnZW5vdHlwZSBmaWxlcwoKYGBge3IsIGV2YWw9Rn0KIyBBc3NlbWJsZSBrZXkgbGlua2luZyBzYW1wbGUtcG9vbCB0byBzaW1wbGlmaWVkIHNhbXBsZQpobGFfc2FtcGxlcyA8LSByZWFkX3RzdihoZXJlKCJkYXRhL2lzYi9zY0hMQWNvdW50L0JMX2Zhc3RxX2ZpbGVzLnR4dCIpLCBjb2xfbmFtZXMgPSAiZmlsZSIpICU+JSAKICBmaWx0ZXIoZ3JlcGwoIl5JTkNPViIsIGZpbGUpKSAlPiUgCiAgZmlsdGVyKGdyZXBsKCItQkwiLCBmaWxlKSkgJT4lIAogIHNlcGFyYXRlKGZpbGUsIGludG8gPSBjKCJzYW1wbGUiLCBOQSksIHNlcCA9ICJfIiwgcmVtb3ZlID0gRikgJT4lIAogIGRyb3BfbmEoKQoKIyBGcm9tIGFsbCBnZW5vdHlwZSBmaWVsZCByZXN1bHRzLCBhc3NlbWJsZSBoaWdoZXN0IHJlc29sdXRpb24gZ2Vub3R5cGUgZm9yIGFsbCBzYW1wbGU6Z2Vub3R5cGVycwpzZWxlY3RfbGFzdF9hbGxlbGUgPC0gZnVuY3Rpb24oeCl7CiAgeFshaXMubmEoeCldICU+JQogICAgdGFpbCgxKSAlPiUgCiAgICBzdHJfcmVwbGFjZV9hbGwoIl8iLCAiOiIpfQpobGFfa2V5IDwtIGFsbF9obGFfZXhwYW5kZWQgJT4lIAogIHJvd3dpc2UoKSAlPiUgCiAgZmlsdGVyKGxvY3VzICVpbiUgYygiQSIsIkIiLCJDIiwiRFBBMSIsIkRQQjEiLCJEUUExIiwiRFFCMSIsIkRSQjEiKSkgJT4lIAogIG11dGF0ZShhbGxlbGUgPSBzZWxlY3RfbGFzdF9hbGxlbGUoYWNyb3NzKGNvbnRhaW5zKCJmaWVsZCIpKSkpICU+JSAKICBzZWxlY3Qoc2FtcGxlLCBnZW5vdHlwZXIsIGxvY3VzLCBhbGxlbGUpICU+JSAKICB1bml0ZShhbGxlbGUsIGxvY3VzLCBhbGxlbGUsIHNlcCA9ICIqIikKCiMgTWVyZ2UgaW50byBrZXkgb2YgbGlzdCBvZiBnZW5vdHlwZXMgZm9yIGVhY2ggc2FtcGxlLXBvb2w6Z2Vub3R5cGVyIHBhaXIKaGxhX21lcmdlIDwtIGhsYV9zYW1wbGVzICU+JSAKICBsZWZ0X2pvaW4oaGxhX2tleSwgYnkgPSAic2FtcGxlIikgJT4lIAogIGRyb3BfbmEoKSAlPiUgCiAgc2VsZWN0KC1zYW1wbGUpICU+JSAKICBncm91cF9ieShmaWxlLCBnZW5vdHlwZXIpICU+JSAKICBuZXN0KCkKCiMgIyBXcml0ZSBrZXlzIHRvIHNldCBvZiBjc3ZzIGZvciBpbnB1dCB0byBzY0hMQWNvdW50CiMgaGxhX21lcmdlICU+JQojICAgbXV0YXRlKHdyaXRlID0gcG1hcChsaXN0KGRhdGEsIGZpbGUsIGdlbm90eXBlciksIGZ1bmN0aW9uKGQsZixnKXsKIyAgICAgZGlyIDwtIGhlcmUoc3ByaW50ZigiZGF0YS9pc2Ivc2NITEFjb3VudC9nZW5vdHlwZXMvJXMiLGcpKQojICAgICBpZiAoIWRpci5leGlzdHMoZGlyKSl7ZGlyLmNyZWF0ZShkaXIsIHJlY3Vyc2l2ZSA9IFQpfQojICAgICB3cml0ZV90c3YoZCwKIyAgICAgICAgICAgICAgIHNwcmludGYoIiVzLyVzX2hsYS50c3YiLGRpcixmKSwKIyAgICAgICAgICAgICAgIGNvbF9uYW1lcyA9IEYsCiMgICAgICAgICAgICAgICApfSkpCmBgYAoKCiMjIyBSdW4gc2NyaXB0Cgpgc2JhdGNoIC9jb3ZpZC9zY3JpcHRzL2lzYl9zY0hMQWNvdW50X2JlbmNobWFyay5zaGAKCmBgYHtiYXNoLCBldmFsPUZ9CiMhL2Jpbi9zaAoKIyBTRVQgR0xPQkFMIFZBUklBQkxFUwojIEdlbmVyYWwKZXhwb3J0IEdJVF9ESVI9L2xhYnMva2hhdHJpbGFiL3NvbG9tb25iL2hsYV9wcm9qZWN0L2hsYV9iZW5jaG1hcmsvZGF0YS9pc2Ivc2NITEFjb3VudApleHBvcnQgQkFTRV9ESVI9L2xhYnMva2hhdHJpbGFiL3NvbG9tb25iL2NvdmlkL2lzYi9zY0hMQWNvdW50CmV4cG9ydCBMT0dfRElSPSRHSVRfRElSL2xvZ3MvJChkYXRlICsnJXklbSVkXyVIJU0lUycpCiMgRkFTVFEvSElTQVQKZXhwb3J0IElOREVYX0RJUj0vbGFicy9raGF0cmlsYWIvc29sb21vbmIvcm5hc2VxX3Byb2Nlc3NpbmcvaGlzYXQyL2hpc2F0X2FyY2FzL2hpc2F0X2RhdGEvZ3JjaDM4CmV4cG9ydCBCQU1fRElSPSRCQVNFX0RJUi9iYW0KIyBITEEgcmVmZXJlbmNlcwpleHBvcnQgSExBX0RJUj0kR0lUX0RJUi9obGFfcmVmZXJlbmNlcwpleHBvcnQgSExBTlVDPS9sYWJzL2toYXRyaWxhYi9zb2xvbW9uYi9yZWZlcmVuY2VzL0lNR1RITEEvaGxhX251Yy5mYXN0YQpleHBvcnQgSExBR0VOPS9sYWJzL2toYXRyaWxhYi9zb2xvbW9uYi9yZWZlcmVuY2VzL0lNR1RITEEvaGxhX2dlbi5mYXN0YQojIFNDSExBCmV4cG9ydCBCQVJDT0RFX0RJUj0kR0lUX0RJUi9iYXJjb2RlcwpleHBvcnQgR0VOT1RZUEVfRElSPSRHSVRfRElSL2dlbm90eXBlcwpleHBvcnQgU0NITEFDT1VOVF9ESVI9JEdJVF9ESVIvb3V0cHV0CmV4cG9ydCBURU1QX0RJUj0kR0lUX0RJUi90ZW1wX2Zhc3RxCiMgU0xVUk0gCmV4cG9ydCBOX0NPUkVTPSRTTFVSTV9DUFVTX1BFUl9UQVNLCgoKIyBDUkVBVEUgRElSRUNUT1JJRVMKaWYgWyAhIC1kICRMT0dfRElSIF07IHRoZW4gbWtkaXIgLXAgJExPR19ESVI7ZmkKaWYgWyAhIC1kICRCQU1fRElSIF07IHRoZW4gbWtkaXIgLXAgJEJBTV9ESVI7ZmkKaWYgWyAhIC1kICRTQ0hMQUNPVU5UX0RJUiBdOyB0aGVuIG1rZGlyIC1wICRTQ0hMQUNPVU5UX0RJUjtmaQppZiBbICEgLWQgJFRFTVBfRElSIF07IHRoZW4gbWtkaXIgLXAgJFRFTVBfRElSO2ZpCgojIENSRUFURSBITEEgUkVGRVJFQ0UgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpITEFfUkVGRVJFTkNFKCl7CiAgc291cmNlIC9sYWJzL2toYXRyaWxhYi9zb2xvbW9uYi9taW5pY29uZGEzL2V0Yy9wcm9maWxlLmQvY29uZGEuc2gKICBjb25kYSBhY3RpdmF0ZSBzYW10b29scwogIAogIHByaW50ZiAiXG5cCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIENSRUFURSBSRUZFUkVOQ0UgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjXAogIFxuIiA+PiAkTE9HX0RJUi8kezF9LyR7MX1fJHsyfS5sb2cKICBwcmludGYgIlxuIyMjIFtTVEFSVF9fX1JFRkVSRU5DRV9fXyQoZGF0ZSArJyVEICVYJyldXG4iID4+ICRMT0dfRElSLyR7MX0vJHsxfV8kezJ9LmxvZwogIAogIFsgISAtZCAkSExBX0RJUi8kezJ9IF0gJiYgbWtkaXIgLXAgJEhMQV9ESVIvJHsyfQogIAogIHdoaWxlIHJlYWQgLXIgbGluZTsgZG8gZ3JlcCAtRiAtbSAxICRsaW5lICRITEFOVUMgPj4gJEhMQV9ESVIvJHsyfS8kezF9X3RtcGFsbGVsZS50eHQ7IGRvbmUgPCAkR0VOT1RZUEVfRElSLyR7Mn0vJHsxfV9obGEudHN2CiAgCiAgc2FtdG9vbHMgZmFpZHggICRITEFOVUMgJChjdXQgLWYxIC1kJyAnICRITEFfRElSLyR7Mn0vJHsxfV90bXBhbGxlbGUudHh0IHwgdHIgJz4nICcgJyB8IHRyICdcbicgJyAnKSA+ICRITEFfRElSLyR7Mn0vJHsxfV9jZHMuZmFzdGEgMj4+ICRMT0dfRElSLyR7MX0vJHsxfV8kezJ9LmxvZwogIHNhbXRvb2xzIGZhaWR4ICAkSExBR0VOICQoY3V0IC1mMSAtZCcgJyAkSExBX0RJUi8kezJ9LyR7MX1fdG1wYWxsZWxlLnR4dCB8IHRyICc+JyAnICcgfCB0ciAnXG4nICcgJykgPiAkSExBX0RJUi8kezJ9LyR7MX1fZ2VuLmZhc3RhIDI+PiAkTE9HX0RJUi8kezF9LyR7MX1fJHsyfS5sb2cKICAKICB3aGlsZSByZWFkIC1yIGxpbmU7IGRvIElGUz0nICc7IHJlYWQgLXIgZjEgZjIgPDw8IiRsaW5lIjsgc2VkIC1pIiIgInMvJGYxLyRmMSAkZjIvZyIgJEhMQV9ESVIvJHsyfS8kezF9X2Nkcy5mYXN0YTsgZG9uZSA8ICRITEFfRElSLyR7Mn0vJHsxfV90bXBhbGxlbGUudHh0IDI+PiAkTE9HX0RJUi8kezF9LyR7MX1fJHsyfS5sb2cKICB3aGlsZSByZWFkIC1yIGxpbmU7IGRvIElGUz0nICc7IHJlYWQgLXIgZjEgZjIgZjMgPDw8IiRsaW5lIjsgc2VkIC1pIiIgInMvJGYxLyRmMSAkZjIvZyIgJEhMQV9ESVIvJHsyfS8kezF9X2dlbi5mYXN0YTsgZG9uZSA8ICRITEFfRElSLyR7Mn0vJHsxfV90bXBhbGxlbGUudHh0IDI+PiAkTE9HX0RJUi8kezF9LyR7MX1fJHsyfS5sb2cKICAKICBybSAkSExBX0RJUi8kezJ9LyR7MX1fdG1wYWxsZWxlLnR4dAogIHByaW50ZiAiIyMjIFtDT01QTEVURV9fX1JFRkVSRU5DRV9fXyQoZGF0ZSArJyVEICVYJyldXG4iID4+ICRMT0dfRElSLyR7MX0vJHsxfV8kezJ9LmxvZwp9CmV4cG9ydCAtZiBITEFfUkVGRVJFTkNFCgoKIyBERUZJTkUgc2NITEEgR0VOT1RZUElORyBQSVBFTElORSAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKU0NITEFDT1VOVCgpewogIHNvdXJjZSAvbGFicy9raGF0cmlsYWIvc29sb21vbmIvbWluaWNvbmRhMy9ldGMvcHJvZmlsZS5kL2NvbmRhLnNoCiAgY29uZGEgYWN0aXZhdGUgc2FtdG9vbHMKICAKICBwcmludGYgIlxuXAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBSVU4gU0NITEFDT1VOVCAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyNcCiAgXG4iID4+ICRMT0dfRElSLyR7MX0vJHsxfV8kezJ9LmxvZwogIHByaW50ZiAiXG4jIyMgW1NUQVJUX19fU0NITEFDT1VOVF9fXyQoZGF0ZSArJyVEICVYJyldXG4iID4+ICRMT0dfRElSLyR7MX0vJHsxfV8kezJ9LmxvZwogIAogIGVjaG8gIiMjIyBTdGFydGluZyAgc2NITEFjb3VudCBhdCAkKGRhdGUgKyclRCAlWCcpIiA+PiAkTE9HX0RJUi8kezF9LyR7MX1fJHsyfS5sb2cKICAKICAjIGlmIFsgLWQgJFNDSExBQ09VTlRfRElSLyR7MX1fcmVzdWx0cyBdOyB0aGVuIHJtIC1yICRTQ0hMQUNPVU5UX0RJUi8kezF9X3Jlc3VsdHM7ZmkKICBbICEgLWQgU0NITEFDT1VOVF9ESVIvJHsyfSBdICYmIG1rZGlyIC1wICRTQ0hMQUNPVU5UX0RJUi8kezJ9CgogIHNjX2hsYV9jb3VudCBcCiAgLS1iYW0gJEJBTV9ESVIvJHsxfS5iYW0gXAogIC0tY2VsbC1iYXJjb2RlcyAkQkFSQ09ERV9ESVIvJHsxfV9iYXJjb2RlLnRzdiBcCiAgLS1vdXQtZGlyICRTQ0hMQUNPVU5UX0RJUi8kezJ9LyR7MX1fcmVzdWx0cyBcCiAgLS1mYXN0YS1jZHMgJEhMQV9ESVIvJHsyfS8kezF9X2Nkcy5mYXN0YSBcCiAgLS1mYXN0YS1nZW5vbWljICRITEFfRElSLyR7Mn0vJHsxfV9nZW4uZmFzdGFcCiAgPj4gJExPR19ESVIvJHsxfS8kezF9XyR7Mn0ubG9nIFwKICAyPj4gJExPR19ESVIvJHsxfS8kezF9XyR7Mn0ubG9nCgogIHByaW50ZiAiIyMjIFtDT01QTEVURV9fX1NDSExBQ09VTlRfX18kKGRhdGUgKyclRCAlWCcpXVxuIiA+PiAkTE9HX0RJUi8kezF9LyR7MX1fJHsyfS5sb2cKfQpleHBvcnQgLWYgU0NITEFDT1VOVAoKCiMgREVGSU5FIFBJUEVMSU5FIENPTlRST0xMRVIgRlVOQ1RJT04gIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjClBJUEVMSU5FKCl7CiAgZWNobyAiU1RBUlQ6IHNhbXBsZSAkMSBhdCAkKGRhdGUgKyclRCAlWCcpIgogIGZvciBHIGluIGFyY2FzSExBIGhsYW1pbmVyIGludml0cm8gb3B0aXR5cGUgcGhsYXQKICBkbwogICAgWyAhIC1kICRMT0dfRElSLyR7MX0gXSAmJiBta2RpciAtcCAkTE9HX0RJUi8kezF9CiAgICBITEFfUkVGRVJFTkNFICQxICRHCiAgICBTQ0hMQUNPVU5UICQxICRHCiAgZG9uZQogIGVjaG8gIkNPTVBMRVRFOiBzYW1wbGUgJDEgYXQgJChkYXRlICsnJUQgJVgnKSIKfQpleHBvcnQgLWYgUElQRUxJTkUKCmNhdCAkR0lUX0RJUi9CTF9mYXN0cV9maWxlcy50eHQgfCBwYXJhbGxlbCAtLWRlbGF5IDE1IC1qICRTTFVSTV9OVEFTS1MgLS1qb2Jsb2cgJExPR19ESVIvcGFyYWxsZWwubG9nIFBJUEVMSU5FIHt9CmBgYAoKCiMgVU1BUCBwcm9qZWN0aW9ucwoKIyMjIENlbGwgY2x1c3RlcnMKCmBgYHtyfQojIHNydCA8LSByZWFkUkRTKCIvbGFicy9raGF0cmlsYWIvaG9uZ3poZW5nL3dlYmFwcHMvaXNiL3NydF9pc2IyNjAubWV0YS5yZHMiKQpzcnQgPC0gcmVhZFJEUyhoZXJlKCJkYXRhL2lzYi9pc2Jfc2NfbWV0YWRhdGEuUkRTIikpCmNlbGxzIDwtIGMoIkNEMTQgTW9ub2N5dGUiLCAiQ0Q0IFQiLCAiQ0Q4IFQiLCAiTksiLCAiQiIsICJDRDE2IE1vbm9jeXRlIiwgImNEQyIsICJwREMiKQpzcnQgPC0gc3J0ICU+JSBzZWxlY3Qoc2FtcGxlLCBzYW1wbGVJRCwgY2VsbCwgY2VsbHR5cGUsIHNldmVyaXR5LCBVTUFQXzEsIFVNQVBfMikgJT4lIAogIGZpbHRlcihjZWxsdHlwZSAlaW4lIGNlbGxzKQpgYGAKCmBgYHtyfQojIGdncGxvdCB0aGVtZSB0byBvdmVybGF5IGNsdXN0ZXIgaWQgI3Mgb24gVU1BUApnZ19zcnRfcmVsYWJlbCA8LSBmdW5jdGlvbihkZiwgeF92YXIsIHlfdmFyLCBjb2xvcl92YXIsIGNlbGxfZnJhY3Rpb24gPSAxKXsKICBwbHQgPC0gZGYgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gISFzeW0oeF92YXIpLCB5ID0gISFzeW0oeV92YXIpLCBjb2xvciA9ICEhc3ltKGNvbG9yX3ZhcikpKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjUsIGFscGhhID0gMC41KSsKICAgIHRoZW1lX2J3KCkgKwogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSsKICAgIGd1aWRlcyhjb2xvciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSAyLCBhbHBoYSA9IDEpKSkKICAKICBnIDwtIGdncGxvdF9idWlsZChwbHQpCiAgCiAgcGx0X2lkcyA8LSBnJGRhdGFbWzFdXQogIGdyb3VwX2xldmVscyA8LSBsZXZlbHMoZmFjdG9yKGckcGxvdCRkYXRhW1tnJHBsb3QkbGFiZWxzJGNvbG91cl1dKSkKICAKICBwbHRfa2V5IDwtIGckZGF0YVtbMV1dICU+JSAKICAgIHNlbGVjdChjb2xvdXIsIGdyb3VwKSAlPiUgCiAgICBkaXN0aW5jdCgpICU+JSAKICAgIG11dGF0ZShsYWJlbCA9IG1hcF9jaHIoZ3JvdXAsIGZ1bmN0aW9uKHgpIGdyb3VwX2xldmVsc1t4XSkpICU+JSAKICAgIG11dGF0ZShsYWJlbCA9IGZhY3RvcihsYWJlbCwgbGV2ZWwgPSBncm91cF9sZXZlbHMpKSAlPiUKICAgIG11dGF0ZShsYWJlbCA9IHNwcmludGYoIiVzKSAlcyIsIDE6bigpLCBsYWJlbCkpICU+JSAKICAgIHNlbGVjdCgtZ3JvdXApCiAgCiAgcGx0X2RmIDwtIHBsdF9pZHMgJT4lIAogICAgbGVmdF9qb2luKHBsdF9rZXksIGJ5ID0gImNvbG91ciIpCiAgCiAgcGx0X2NlbnRlciA8LSBwbHRfZGYgJT4lIAogICAgZ3JvdXBfYnkobGFiZWwpICU+JSBzdW1tYXJpc2UoeCA9IG1lYW4oeCksIHkgPSBtZWFuKHkpKSAlPiUKICAgIG11dGF0ZShsYWJlbCA9IGdzdWIoIikuKiIsIiIsbGFiZWwpKQogIAogIHBsdF9yZXBlbCA8LSBwbHRfZGYgJT4lIAogICAgZ2dwbG90KGFlcyh4PXgseT15LGNvbG9yPWxhYmVsKSkgKwogICAgZ2VvbV9wb2ludChzaXplID0gMC41KSsKICAgIGdncmVwZWw6Omdlb21fdGV4dF9yZXBlbChkYXRhPXBsdF9jZW50ZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKGxhYmVsPWxhYmVsLCAgYmcuY29sb3I9IndoaXRlIiwgYmcucj0wLjI1KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udGZhY2UgPSAiYm9sZCIpICsKICAgIHRoZW1lX2J3KCkgKwogICAgZ3VpZGVzKGNvbG9yID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZSA9IDIpICkgKSArCiAgICBsYWJzKHg9eF92YXIsIHkgPSB5X3ZhciwgY29sb3IgPSBjb2xvcl92YXIpICsKICAgIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSkKICByZXR1cm4ocGx0X3JlcGVsKQp9CgpwbHRfc3J0IDwtIHNydCAlPiUgCiAgZmlsdGVyKGNlbGx0eXBlICVpbiUgY2VsbHMpICU+JSAKICBmaWx0ZXIoc2FtcGxlSUQgPT0gIklOQ09WMDY5LUJMIikgJT4lIAogIGdnX3NydF9yZWxhYmVsKHhfdmFyID0gIlVNQVBfMSIsIHlfdmFyID0gIlVNQVBfMiIsIGNvbG9yX3ZhciA9ICJjZWxsdHlwZSIsIGNlbGxfZnJhY3Rpb24gPSAwLjEpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIpKyAKICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCkpICsKICBsYWJzKHg9IlVNQVAgMSIsIHkgPSAiVU1BUCAyIiwgY29sb3IgPSAiQ2VsbCBDbHVzdGVyIikKcGx0X3NydApgYGAKIyMjIEFsbGVsZSBmcmVxdWVuY3kKCmBgYHtyfQojIHNhbXAgPC0gIklOQ09WMDY5LUJMIgojIHNhbXAgPC0gIklOQ09WMDIyLUJMIgojIHNhbXAgPC0gIklOQ09WMDgzLUJMIgpzYW1wIDwtICJJTkNPVjAyOC1CTCIKc2NITEFjb3VudF9kaXIgPC0gc3ByaW50ZigiJXMvc2NITEFjb3VudCIsIGlzYl9wYXRoKQoKIyBDcmVhdGUgdGliYmxlIG9mIGFsbCBnZW5vdHlwZXIgYW5kIHNhbXBsZSBjb21iaW5hdGlvbnMKYWxsZWxlX2RhdGEgPC0gZXhwYW5kX2dyaWQoCiAgZ2Vub3R5cGVyID0gYygiaW52aXRybyIsICJhcmNhc0hMQSIsICJvcHRpdHlwZSIsICJwaGxhdCIsICJobGFtaW5lciIpLAogIHNhbXBsZSA9IHJlYWRfbGluZXMoaGVyZSgiZGF0YS9pc2Ivc2NITEFjb3VudC9CTF9mYXN0cV9maWxlcy50eHQiKSkpICU+JSAKICBmaWx0ZXIoZ3JlcGwoc2FtcCwgc2FtcGxlKSkgJT4lIAogICMgSW1wb3J0IGRhdGEgYmFzZWQgb24gc2FtcGxlIGFuZCBnZW5vdHlwZXIKICBtdXRhdGUocmVzdWx0X3BhdGggPSBzcHJpbnRmKCIlcy9zY0hMQWNvdW50L291dHB1dC8lcyIsaXNiX3BhdGgsIGdlbm90eXBlciksCiAgICAgICAgIGJhcmNvZGVfcGF0aCA9IHNwcmludGYoIiVzL3NjSExBY291bnQvYmFyY29kZXMiLCBpc2JfcGF0aCkpICU+JSAKICBtdXRhdGUoZGF0YSA9IHBtYXAobGlzdChzYW1wbGUsIHJlc3VsdF9wYXRoLCBiYXJjb2RlX3BhdGgpLCBmdW5jdGlvbihzLHIsYil7CiAgICBkZiA8LSBzY0hMQV9kYXRhX3Byb2Nlc3NpbmcoCiAgICAgIHNhbXBsZT1zLAogICAgICByZXN1bHRfZGlyPXIsCiAgICAgIGJhcmNvZGVfZGlyPWIKICAgICkgCiAgfSkpICU+JSB1bm5lc3QoZGF0YSkKYGBgCgpgYGB7ciwgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQgPSA2fQpwbG90X2FsbGVsZV9mcmVxdWVuY2llcyA8LSBmdW5jdGlvbihhbGxlbGVfZGF0YSwgZ2VuZV9zZWxlY3QpewoKICBhbGxlbGVfZGF0YV9yYXRpb3MgPC0gYWxsZWxlX2RhdGEgJT4lIAogICAgZmlsdGVyKGdlbmUgPT0gZ2VuZV9zZWxlY3QpICU+JSAKICAgIG11dGF0ZShnZW5vdHlwZXIgPSByZWZvcm1hdF9obGFfZ2Vub3R5cGVyKGdlbm90eXBlcikpICU+JSAKICAgIG11dGF0ZShhbGxlbGVfb3JkZXIgPSBmY3RfcmVjb2RlKGZhY3RvcihhbGxlbGVfb3JkZXIpLCAiQWxsZWxlIDEiID0gIjEiLCAiQWxsZWxlIDIiID0gIjIiKSkKICAgIAogIGFsbGVsZV9sYWJlbCA8LSBhbGxlbGVfZGF0YV9yYXRpb3MgJT4lIAogICAgc2VsZWN0KGdlbm90eXBlciwgYWxsZWxlX29yZGVyLCBhbGxlbGUpICU+JSAKICAgIGRpc3RpbmN0KCkKICAKICBwbHQgPC0gc3J0ICU+JSAKICAgIGxlZnRfam9pbihhbGxlbGVfZGF0YV9yYXRpb3MgJT4lIGZpbHRlcihnZW5lID09IGdlbmVfc2VsZWN0KSwgYnkgPSAiY2VsbCIpICU+JSAKICAgIGZpbHRlcighaXMubmEoYWxsZWxlKSkgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gVU1BUF8xLCB5ID0gVU1BUF8yLCBjb2xvciA9IGFsbGVsZV9yYXRpbykpICsKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjUpKwogICAgdGhlbWVfYncoKSArCiAgICBmYWNldF9ncmlkKGFsbGVsZV9vcmRlcn5nZW5vdHlwZXIpKwogICAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKGhpZ2ggPSAicmVkIiwgbWlkID0gImdyZXk4MCIsIGxvdyA9ICJibHVlIiwgbWlkcG9pbnQgPSAwLjUsIG5hLnZhbHVlID0gInRyYW5zcGFyZW50IikgKwogICAgbGFicyh4PSJVTUFQIDEiLCB5PSJVTUFQIDIiLCBjb2xvciA9ICJBbGxlbGUgXG5GcmVxdWVuY3kiKSsKICAgIHRoZW1lKGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSkrCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTEwLDE1KSkKICAKICBwbHRfYWxsZWxlX2ZyZXEgPC0gcGx0KwogICAgZ2VvbV9sYWJlbChkYXRhID0gYWxsZWxlX2xhYmVsLCBhZXMoeD0tMTAseT0xNCwgY29sb3IgPSBOVUxMLCBsYWJlbCA9IGFsbGVsZSksIHNpemUgPSAzLCBoanVzdCA9IDApCiAgCiAgcmV0dXJuKHBsdF9hbGxlbGVfZnJlcSkKfQoKcGx0X2FsbGVsZV9mcmVxIDwtIHBsb3RfYWxsZWxlX2ZyZXF1ZW5jaWVzKGFsbGVsZV9kYXRhID0gYWxsZWxlX2RhdGEsIGdlbmVfc2VsZWN0ID0gIkEiKQpwbHRfYWxsZWxlX2ZyZXEKYGBgCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodCA9IDZ9CnBsb3RfYWxsZWxlX2ZyZXF1ZW5jaWVzKGFsbGVsZV9kYXRhID0gYWxsZWxlX2RhdGEsIGdlbmVfc2VsZWN0ID0gIkRSQjEiKQpgYGAKCiMjIyBNYXhpbXVtIGFsbGVsZQoKYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0ID0gMywgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQpwbG90X2FsbGVsZV9yYXRpb3MgPC0gZnVuY3Rpb24oYWxsZWxlX2RhdGEsIGdlbmVfc2VsZWN0KXsKICAjIENyZWF0ZSB0aWJibGUgb2YgYWxsIGdlbm90eXBlciBhbmQgc2FtcGxlIGNvbWJpbmF0aW9ucwogIGFsbGVsZV9tYXhfcmF0aW8gPC0gYWxsZWxlX2RhdGEgICU+JQogICAgc2VsZWN0KGdlbm90eXBlciwgY2VsbCwgZ2VuZSwgYWxsZWxlX29yZGVyLCBhbGxlbGVfcmF0aW8pICU+JQogICAgIyBncm91cF9ieShnZW5vdHlwZXIsIGNlbGwsIGFsbGVsZV9vcmRlcikgJT4lICBtdXRhdGUodGVzdCA9IGxlbmd0aChhbGxlbGVfb3JkZXIpKQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9ICJhbGxlbGVfb3JkZXIiLCB2YWx1ZXNfZnJvbSA9ICJhbGxlbGVfcmF0aW8iLCBuYW1lc19wcmVmaXggPSAiYWxsZWxlXyIpICU+JQogICAgcm93d2lzZSgpICU+JQogICAgbXV0YXRlKG1heF9yYXRpbyA9IG1heChhY3Jvc3MoY29udGFpbnMoImFsbGVsZV8iKSksIG5hLnJtID0gVCkpICU+JQogICAgc2VsZWN0KGdlbm90eXBlciwgY2VsbCwgZ2VuZSwgbWF4X3JhdGlvKSAlPiUKICAgIGZpbHRlcihnZW5lID09IGdlbmVfc2VsZWN0KSAKICAKICBhbGxlbGVfbGFiZWwgPC0gYWxsZWxlX2RhdGEgJT4lIHNlbGVjdChzYW1wbGUsIGdlbm90eXBlciwgZ2VuZSwgYWxsZWxlKSAlPiUgCiAgICBmaWx0ZXIoZ2VuZSA9PSBnZW5lX3NlbGVjdCkgJT4lIAogICAgc2VwYXJhdGUoc2FtcGxlLCBpbnRvID0gYygic2FtcGxlIiwgTlVMTCksIHNlcCA9ICJfIiwgZXh0cmEgPSAiZHJvcCIpICU+JSAKICAgIGRpc3RpbmN0KCkgJT4lIAogICAgZ3JvdXBfYnkoc2FtcGxlLCBnZW5vdHlwZXIsIGdlbmUpICU+JSBuZXN0KCkgJT4lIHVubmVzdF93aWRlcihkYXRhKSAlPiUgCiAgICBtdXRhdGUoZ2Vub3R5cGVyID0gcmVmb3JtYXRfaGxhX2dlbm90eXBlcihnZW5vdHlwZXIpKSAlPiUgCiAgICBtdXRhdGUoYWxsZWxlID0gbWFwX2NocihhbGxlbGUsIHBhc3RlLCBjb2xsYXBzZSA9ICJcbiIpKQogIAogIHBsdF9tYXhfYWxsZWxlIDwtIHNydCAlPiUgCiAgICBsZWZ0X2pvaW4oYWxsZWxlX21heF9yYXRpbyAlPiUgZmlsdGVyKGdlbmUgPT0gZ2VuZV9zZWxlY3QpLCBieSA9ICJjZWxsIikgJT4lIAogICAgIyBtdXRhdGUoZ2Vub3R5cGVyID0gZmN0X3JlbGV2ZWwoZ2Vub3R5cGVyLCAiaW52aXRybyIpKSAlPiUgCiAgICBtdXRhdGUoZ2Vub3R5cGVyID0gcmVmb3JtYXRfaGxhX2dlbm90eXBlcihnZW5vdHlwZXIpKSAlPiUgCiAgICBmaWx0ZXIoIWlzLm5hKGdlbm90eXBlcikpICU+JQogICAgZ2dwbG90KGFlcyh4ID0gVU1BUF8xLCB5ID0gVU1BUF8yLCBjb2xvciA9IG1heF9yYXRpbykpICsKICAgICAgZ2VvbV9wb2ludChzaXplID0gMC41LCBhbHBoYSA9IDAuNSkrCiAgICAgIGdlb21fbGFiZWwoZGF0YSA9IGFsbGVsZV9sYWJlbCwgYWVzKGNvbG9yID0gTlVMTCwgbGFiZWwgPSBhbGxlbGUsIHggPSAtSW5mLCB5ID0gLUluZiksCiAgICAgICAgICAgICAgaGp1c3QgPSAtMC4xLCB2anVzdCA9IC0wLjEsIHNpemUgPSAzLCBoanVzdCA9IDApICsKICAgICAgdGhlbWVfYncoKSArCiAgICAgIGZhY2V0X2dyaWQoLn5nZW5vdHlwZXIpKwogICAgICBzY2FsZV9jb2xvcl9ncmFkaWVudChoaWdoID0gInJlZCIsIGxvdyA9ICJibHVlIiwgbmEudmFsdWUgPSAidHJhbnNwYXJlbnQiKSArCiAgICAgIGxhYnMoeD0iVU1BUCAxIiwgeT0iVU1BUCAyIiwgY29sb3IgPSAiTWF4aW11bSBBbGxlbGUgXG5GcmVxdWVuY3kiKSsKICAgICAgdGhlbWUoYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpKQogIAogIHJldHVybihwbHRfbWF4X2FsbGVsZSkKfQoKcGx0X21heF9hbGxlbGUgPC0gcGxvdF9hbGxlbGVfcmF0aW9zKGFsbGVsZV9kYXRhID0gYWxsZWxlX2RhdGEsIGdlbmVfc2VsZWN0ID0gIkEiKQpwbHRfbWF4X2FsbGVsZQpgYGAKYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0ID0gMywgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQpwbG90X2FsbGVsZV9yYXRpb3MoYWxsZWxlX2RhdGEgPSBhbGxlbGVfZGF0YSwgZ2VuZV9zZWxlY3QgPSAiRFJCMSIpCmBgYAoKYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0ID0gMywgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQphbGxlbGVfbWF4X3JhdGlvIDwtIGFsbGVsZV9kYXRhICAlPiUKICAgIGZpbHRlcihnZW5vdHlwZXIgPT0gImludml0cm8iKSAlPiUgIAogICAgc2VsZWN0KGNlbGwsIGdlbmUsIGFsbGVsZV9vcmRlciwgYWxsZWxlX3JhdGlvKSAlPiUKICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSAiYWxsZWxlX29yZGVyIiwgdmFsdWVzX2Zyb20gPSAiYWxsZWxlX3JhdGlvIiwgbmFtZXNfcHJlZml4ID0gImFsbGVsZV8iKSAlPiUKICAgIHJvd3dpc2UoKSAlPiUKICAgIG11dGF0ZShtYXhfcmF0aW8gPSBtYXgoYWNyb3NzKGNvbnRhaW5zKCJhbGxlbGVfIikpLCBuYS5ybSA9IFQpKSAlPiUKICAgIHNlbGVjdChjZWxsLCBnZW5lLCBtYXhfcmF0aW8pCiAgCmFsbGVsZV9sYWJlbCA8LSBhbGxlbGVfZGF0YSAlPiUgIAogIGZpbHRlcihnZW5vdHlwZXIgPT0gImludml0cm8iKSAlPiUgCiAgc2VsZWN0KHNhbXBsZSwgZ2VuZSwgYWxsZWxlKSAlPiUKICBzZXBhcmF0ZShzYW1wbGUsIGludG8gPSBjKCJzYW1wbGUiLCBOVUxMKSwgc2VwID0gIl8iLCBleHRyYSA9ICJkcm9wIikgJT4lIAogIGRpc3RpbmN0KCkgJT4lIAogIGdyb3VwX2J5KHNhbXBsZSwgZ2VuZSkgJT4lIG5lc3QoKSAlPiUgdW5uZXN0X3dpZGVyKGRhdGEpICU+JSAKICBtdXRhdGUoYWxsZWxlID0gbWFwX2NocihhbGxlbGUsIHBhc3RlLCBjb2xsYXBzZSA9ICJcbiIpKQoKc3J0ICU+JSAKICBsZWZ0X2pvaW4oYWxsZWxlX21heF9yYXRpbywgYnkgPSAiY2VsbCIpICU+JSAKICAjIG11dGF0ZShnZW5vdHlwZXIgPSBmY3RfcmVsZXZlbChnZW5vdHlwZXIsICJpbnZpdHJvIikpICU+JSAKICBmaWx0ZXIoIWlzLm5hKG1heF9yYXRpbykpICU+JQogIGdncGxvdChhZXMoeCA9IFVNQVBfMSwgeSA9IFVNQVBfMiwgY29sb3IgPSBtYXhfcmF0aW8pKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjUsIGFscGhhID0gMC41KSsKICAgIGdlb21fbGFiZWwoZGF0YSA9IGFsbGVsZV9sYWJlbCwgYWVzKGNvbG9yID0gTlVMTCwgbGFiZWwgPSBhbGxlbGUsIHggPSAtSW5mLCB5ID0gLUluZiksCiAgICAgICAgICAgIGhqdXN0ID0gLTAuMSwgdmp1c3QgPSAtMC4xLCBzaXplID0gMywgaGp1c3QgPSAwKSArCiAgICB0aGVtZV9idygpICsKICAgIGZhY2V0X2dyaWQoLn5nZW5lKSsKICAgIHNjYWxlX2NvbG9yX2dyYWRpZW50KGhpZ2ggPSAicmVkIiwgbG93ID0gImJsdWUiLCBuYS52YWx1ZSA9ICJ0cmFuc3BhcmVudCIpICsKICAgIGxhYnMoeD0iVU1BUCAxIiwgeT0iVU1BUCAyIiwgY29sb3IgPSAiTWF4aW11bSBBbGxlbGUgXG5GcmVxdWVuY3kiKSsKICAgIHRoZW1lKGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSkKYGBgCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodCA9IDgsIHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRn0KICBhbGxlbGVfbWF4X3JhdGlvIDwtIGFsbGVsZV9kYXRhICAlPiUKICAgIHNlbGVjdChnZW5vdHlwZXIsIGNlbGwsIGdlbmUsIGFsbGVsZV9vcmRlciwgYWxsZWxlX3JhdGlvKSAlPiUKICAgICMgZ3JvdXBfYnkoZ2Vub3R5cGVyLCBjZWxsLCBhbGxlbGVfb3JkZXIpICU+JSAgbXV0YXRlKHRlc3QgPSBsZW5ndGgoYWxsZWxlX29yZGVyKSkKICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSAiYWxsZWxlX29yZGVyIiwgdmFsdWVzX2Zyb20gPSAiYWxsZWxlX3JhdGlvIiwgbmFtZXNfcHJlZml4ID0gImFsbGVsZV8iKSAlPiUKICAgIHJvd3dpc2UoKSAlPiUKICAgIG11dGF0ZShtYXhfcmF0aW8gPSBtYXgoYWNyb3NzKGNvbnRhaW5zKCJhbGxlbGVfIikpLCBuYS5ybSA9IFQpKSAlPiUKICAgIHNlbGVjdChnZW5vdHlwZXIsIGNlbGwsIGdlbmUsIG1heF9yYXRpbykKICAKICBhbGxlbGVfbGFiZWwgPC0gYWxsZWxlX2RhdGEgJT4lIHNlbGVjdChzYW1wbGUsIGdlbm90eXBlciwgZ2VuZSwgYWxsZWxlKSAlPiUgCiAgICBzZXBhcmF0ZShzYW1wbGUsIGludG8gPSBjKCJzYW1wbGUiLCBOVUxMKSwgc2VwID0gIl8iLCBleHRyYSA9ICJkcm9wIikgJT4lIAogICAgZGlzdGluY3QoKSAlPiUgCiAgICBncm91cF9ieShzYW1wbGUsIGdlbm90eXBlciwgZ2VuZSkgJT4lIG5lc3QoKSAlPiUgdW5uZXN0X3dpZGVyKGRhdGEpICU+JSAKICAgIG11dGF0ZShnZW5vdHlwZXIgPSByZWZvcm1hdF9obGFfZ2Vub3R5cGVyKGdlbm90eXBlcikpICU+JSAKICAgIG11dGF0ZShhbGxlbGUgPSBtYXBfY2hyKGFsbGVsZSwgcGFzdGUsIGNvbGxhcHNlID0gIlxuIikpCiAgCiAgcGx0X21heF9hbGxlbGVfYWxsR2VuZXNUeXBlcnMgPC0gc3J0ICU+JSAKICAgIGxlZnRfam9pbihhbGxlbGVfbWF4X3JhdGlvLCBieSA9IGMoImNlbGwiKSkgJT4lIAogICAgIyBtdXRhdGUoZ2Vub3R5cGVyID0gZmN0X3JlbGV2ZWwoZ2Vub3R5cGVyLCAiaW52aXRybyIpKSAlPiUgCiAgICBtdXRhdGUoZ2Vub3R5cGVyID0gcmVmb3JtYXRfaGxhX2dlbm90eXBlcihnZW5vdHlwZXIpKSAlPiUgCiAgICBmaWx0ZXIoIWlzLm5hKG1heF9yYXRpbykpICU+JQogICAgZ2dwbG90KGFlcyh4ID0gVU1BUF8xLCB5ID0gVU1BUF8yLCBjb2xvciA9IG1heF9yYXRpbykpICsKICAgICAgcmFzdGVyaXNlKGdlb21fcG9pbnQoc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjUpLCBkcGkgPSAzMDApKwogICAgICBnZW9tX2xhYmVsKGRhdGEgPSBhbGxlbGVfbGFiZWwsIGFlcyhjb2xvciA9IE5VTEwsIGxhYmVsID0gYWxsZWxlLCB4ID0gLUluZiwgeSA9IC1JbmYpLAogICAgICAgICAgICAgIGhqdXN0ID0gLTAuMSwgdmp1c3QgPSAtMC4xLCBzaXplID0gMywgaGp1c3QgPSAwKSArCiAgICAgIHRoZW1lX2J3KCkgKwogICAgICBmYWNldF9ncmlkKGdlbm90eXBlcn5nZW5lKSsKICAgICAgc2NhbGVfY29sb3JfZ3JhZGllbnQoaGlnaCA9ICJyZWQiLCBsb3cgPSAiYmx1ZSIsIG5hLnZhbHVlID0gInRyYW5zcGFyZW50IikgKwogICAgICBsYWJzKHg9IlVNQVAgMSIsIHk9IlVNQVAgMiIsIGNvbG9yID0gIk1heGltdW0gQWxsZWxlIFxuRnJlcXVlbmN5IikrCiAgICAgIHRoZW1lKGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSkKICAKICBwbHRfbWF4X2FsbGVsZV9hbGxHZW5lc1R5cGVycwpgYGAKCiMgTWV0YS1hbmFseXNpcyBhcHByb2FjaAoKIyMjIFJhdGlvbmFsZSAKCi0gR29hbDogZGV0ZXJtaW5lIGEgc3VtbWFyeSBzdGF0aXN0aWMgZm9yIGFsbGVsZSByYXRpbyBhY3Jvc3MgYWxsIGNlbGxzCi0gUHJvYmxlbToKICAtIEVhY2ggY2VsbCBpbiBzY1JOQSBleHBlcmltZW50IGhhcyBpdHMgb3duIHJhdGlvIG9mIEhMQSBhbGxlbGUgMSByZWFkcyA6IEhMQSBhbGxlbGUgMiByZWFkcwogIC0gQSB3aWRlIHJhbmdlIG9mIHRvdGFsIHJlYWQgY291bnRzIG1heSBnbyBpbnRvIGVhY2ggY2VsbCdzIHJhdGlvCiAgLSBTbWFsbCBkaWZmZXJlbmNlIGluIHJlYWQgY291bnRzIGZvciBjZWxscyB3aXRoIGxvdyB0b3RhbCByZWFkcyBjYW4gZ3JlYXRseSBhbHRlciB0aGUgYWxsZWxlIHJhdGlvIGNvbXBhcmVkIHRvIGNlbGxzIHdpdGggaGlnaCB0b3RhbCByZWFkIGNvdW50cwogICAgLSBJLmUuIENlbGxzIHdpdGggbG93IHJlYWQgY291bnRzIGFyZSBtb3JlIGxpa2VseSB0byBoYXZlIGltcHJlY2lzZSBhbGxlbGUgcmF0aW9zCiAgLSBTaW1wbHkgYXZlcmFnaW5nIHJhdGlvcyB3b3VsZCBlcXVhbGx5IHdlaWdodCBoaWdoIGNvbmZpZGVuY2UsIGhpZ2ggcmVhZCBjb3VudCByYXRpb3Mgd2l0aCBsb3cgY29uZmlkZW5jZSwgbG93IHJlYWQgcmF0aW9zCi0gQXBwcm9hY2gKICAtIE1ldGEtYW5hbHlzaXMgbWV0aG9kcyBzcGVjaWZpY2FsbHkgYWRkcmVzcyB0eXBlIG9mIHByb2JsZW0sIHR5cGljYWxseSBieSB3ZWlnaGluZyBhbiBlZmZlY3QgYnkgdGhlIGludmVyc2Ugb2YgaXRzIHZhcmlhbmNlCiAgLSBJbiB0aGUgc2V0dGluZyBvZiByYXRpb3MsIGJhc2ljIGFwcHJvYWNoIHdvdWxkIGJlIHRvIGNvbWJpbmUgbG9nLW9kZHMgcmF0aW8gb2YgYWxsZWxlcywgd2VpZ2h0ZWQgYnkgaW52ZXJzZSB2YXJpYW5jZQogIC0gV291bGQgdXNlIGEgcmFuZG9tIGVmZmVjdHMgbW9kZWwgYmVjYXVzZSBkbyBub3QgZXhwZWN0IGVhY2ggY2VsbCBpbiBhIGdyb3VwIHdvdWxkIGhhdmUgdGhlIHNhbWUgZXhhY3QgcmF0aW8gZHVlIHRvIHZhcmlvdXMgc3RvY2hhc3RpYyB0cmFuc2NyaXB0aW9uYWwgZWZmZWN0cwoKIyMjIENhbGN1bGF0aW5nIHN1bW1hcnkgZWZmZWN0IHNpemVzCgotIEFuYWx5c2lzIGNhbiB0YWtlIHNvbWUgdGltZSwgc28gcnVuIG9uIGFuIEhQQyBjbHVzdGVyIHVzaW5nIHNsdXJtCi0gQ29udGFpbmVkIGluIGEgc2VwYXJhdGUgc2NyaXB0IGBzY19tZXRhLlJgOgoKIyMjIyBDb250ZW50cyBvZiBgc2NfbWV0YS5SYAoKYGBge3IsIGV2YWwgPSBGfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShtZXRhKQoKc291cmNlKGhlcmUoImhlbHBlcl9mdW5jdGlvbnMvZGF0YV9pbXBvcnRfZnVuY3Rpb25zLlIiKSkKaXNiX3BhdGggPC0gaGVyZSgiZGF0YS9pc2IiKQoKc3J0IDwtIHJlYWRSRFMoaGVyZSgiZGF0YS9pc2IvaXNiX3NjX21ldGFkYXRhLlJEUyIpKQpjZWxscyA8LSBjKCJDRDE0IE1vbm9jeXRlIiwgIkNENCBUIiwgIkNEOCBUIiwgIk5LIiwgIkIiLCAiQ0QxNiBNb25vY3l0ZSIsICJjREMiLCAicERDIikKc3J0IDwtIHNydCAlPiUgc2VsZWN0KHNhbXBsZSwgc2FtcGxlSUQsIGNlbGwsIGNlbGx0eXBlLCBzZXZlcml0eSwgVU1BUF8xLCBVTUFQXzIpICU+JSAKICBmaWx0ZXIoY2VsbHR5cGUgJWluJSBjZWxscykKCiMgRnVuY3Rpb24gdG8gcGVyZm9ybSBtZXRhLWFuYWx5c2lzIG9uIGRhdGFmcmFtZSB3aGVyZQojIGVhY2ggcm93IGlzIGEgY2VsbCBhbmQgY29sdW1uczoKIyBgb2JzZXJ2ZWRgIChyZWFkcyBvZiBkb21pbmFudCBhbGxlbGUpCiMgYGdlbmVfc3VtX3R5cGVkYCAodG90YWwgY2VsbCByZWFkcykKIyBgZXhwZWN0ZWRgIChyZWFkcyBvZiBvbmUgYWxsZWxlIGV4cGVjdGVkIGlmIDUwOjUwIGFsbGVsZV8xIDogYWxsZWxlXzIpCnNjX21ldGEgPC0gZnVuY3Rpb24oZGYpewogIGwgPC0gbnJvdyhkZikKICBtIDwtIG1ldGFiaW4oZXZlbnQuZSA9IG9ic2VydmVkLCBuLmUgPSBnZW5lX3N1bV90eXBlZCwgZXZlbnQuYyA9IGV4cGVjdGVkLCBuLmMgPSBnZW5lX3N1bV90eXBlZCwKICAgICAgICAgICAgICAgZGF0YSA9IGRmLAogICAgICAgICAgICAgICBtZXRob2QgPSAiSW52ZXJzZSIsCiAgICAgICAgICAgICAgIGluY3IgPSAwLjEsCiAgICAgICAgICAgICAgIHNtID0gIk9SIikKICBkYXRhLmZyYW1lKHN1bW1hcnkobSkkcmFuZG9tKSAlPiUgCiAgICBtdXRhdGUobl9jZWxscyA9IGwpICU+JSAKICAgIHNlbGVjdChURSwgc2VURSwgbG93ZXIsIHVwcGVyLCBuX2NlbGxzKSAKfQoKIyBJbXBvcnQgZGF0YSBiYXNlZCBvbiBzYW1wbGUgYW5kIGdlbm90eXBlcgpjZWxsX3N0YXRzIDwtIGV4cGFuZF9ncmlkKAogIGdlbm90eXBlciA9IGMoImludml0cm8iLCAiYXJjYXNITEEiLCAib3B0aXR5cGUiLCAicGhsYXQiLCAiaGxhbWluZXIiKSwKICBzYW1wbGUgPSByZWFkX2xpbmVzKGhlcmUoImRhdGEvaXNiL3NjSExBY291bnQvQkxfZmFzdHFfZmlsZXMudHh0IikpKSAlPiUgCiAgIyBoZWFkKDUpICU+JSAjIFNwZWNpZnkgbGltaXQgdG8gbnVtYmVyIG9mIG1ldGEtYW5hbHlzZXMKICBtdXRhdGUoZGF0YSA9IG1hcDIoc2FtcGxlLCBnZW5vdHlwZXIsIGZ1bmN0aW9uKHMsZyl7CiAgICByZXN1bHRfcGF0aCA9IHNwcmludGYoIiVzL3NjSExBY291bnQvb3V0cHV0X2FzZS8lcyIsaXNiX3BhdGgsIGcpCiAgICBiYXJjb2RlX3BhdGggPSBzcHJpbnRmKCIlcy9zY0hMQWNvdW50L2JhcmNvZGVzIiwgaXNiX3BhdGgpCiAgICBzY0hMQV9kYXRhX3Byb2Nlc3Npbmcoc2FtcGxlID0gcywKICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRfZGlyID0gcmVzdWx0X3BhdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgYmFyY29kZV9kaXIgPSBiYXJjb2RlX3BhdGgpCiAgfSkpICU+JSB1bm5lc3QoZGF0YSkgJT4lIAogIGZpbHRlcighaXMubmEoY2VsbCkpICU+JSAKICBtdXRhdGUoc2FtcGxlID0gZ3N1YigiX1tBLVpdWzAtOV0kIiwiIixzYW1wbGUpKSAlPiUgIyBDb25zb2xpZGF0ZSBzYW1wbGVzCiAgbGVmdF9qb2luKHNydCAlPiUgc2VsZWN0KGNlbGx0eXBlLCBjZWxsKSwgYnkgPSAiY2VsbCIpICU+JSAjIEFkZCBjZWxsdHlwZXMKICBmaWx0ZXIoY2VsbHR5cGUgJWluJSBjZWxscykgIyBLZWVwIG9ubHkgc3RhbmRhcmQgY2VsbCB0eXBlcwoKbWV0YV9kZiA8LSBjZWxsX3N0YXRzICU+JSAKICAjIEtlZXAgb25seSBtb3N0IGV4cHJlc3NlZCBhbGxlbGUgKG9yIHJhbmRvbSBpZiA1MDo1MCkKICBncm91cF9ieShzYW1wbGUsIGdlbm90eXBlciwgZ2VuZSwgY2VsbCkgJT4lIAogIHNsaWNlX21heChvcmRlcl9ieSA9IGFsbGVsZV9yYXRpbywgbiA9IDEsIHdpdGhfdGllcyA9IEYpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogICMgRmlsbCBvdXQgY29udGluZ2VuY3kgdGFibGUKICBtdXRhdGUoY29tcGxlbWVudCA9IGdlbmVfc3VtX3R5cGVkIC0gY291bnQsIAogICAgICAgICBleHBlY3RlZCA9IDAuNSpnZW5lX3N1bV90eXBlZCkgJT4lIAogIHJlbmFtZShvYnNlcnZlZCA9IGNvdW50KSAlPiUgCiAgc2VsZWN0KHNhbXBsZSwgZ2Vub3R5cGVyLCBjZWxsdHlwZSwgZ2VuZSwgb2JzZXJ2ZWQsIGV4cGVjdGVkLCBnZW5lX3N1bV90eXBlZCkgJT4lIAogIGdyb3VwX2J5KHNhbXBsZSwgZ2Vub3R5cGVyLCBjZWxsdHlwZSwgZ2VuZSkgJT4lCiAgIyBOZXN0IGFuZCBydW4gbWV0YS1hbmFseXNpcwogIG5lc3QoKSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIG11dGF0ZShkYXRhID0gbWFwKGRhdGEsZnVuY3Rpb24oeCkge3NjX21ldGEoeCl9KSkgJT4lCiAgdW5uZXN0KGRhdGEpCgp3cml0ZV9jc3YobWV0YV9kZiwgaGVyZSgiN19ITEFfQVNFL21ldGFfYW5hbHlzaXNfcmVzdWx0c18xMi5jc3YiKSkKYGBgCgojIyMgU2luZ2xlIHNhbXBsZSBhbmFseXNpcwoKYGBge3IsIG1lc3NhZ2U9Riwgd2FybmluZz1GfQptZXRhX2RmIDwtIHJlYWRfY3N2KGhlcmUoIjdfSExBX0FTRS9tZXRhX2FuYWx5c2lzX3Jlc3VsdHNfYzEyLmNzdiIpKSAKbWV0YV9kZgpgYGAKYGBge3IsIGZpZy53aWR0aD0zLCBmaWcuaGVpZ2h0PTN9CnBsb3RfbWV0YV9vZGRzIDwtIGZ1bmN0aW9uKGRmLCBjZWxsX3R5cGUsIGxvY3VzKXsKICBkZiAlPiUgCiAgZmlsdGVyKGNlbGx0eXBlID09IGNlbGxfdHlwZSwgZ2VuZSA9PSBsb2N1cykgJT4lIAogIG11dGF0ZShnZW5vdHlwZXIgPSByZWZvcm1hdF9obGFfZ2Vub3R5cGVyKGdlbm90eXBlcikpICU+JQogIGdncGxvdChhZXMoeCA9IGdlbm90eXBlciwgeSA9IFRFLCB5bWluID0gbG93ZXIsIHltYXggPSB1cHBlcikpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX2Vycm9yYmFyKHdpZHRoID0gMC40KSsKICB0aGVtZV9idygpKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsTkEpKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgbGFicyh5ID0gIkxvZy1PZGRzIHJhdGlvIG9mIGRvbWluYW50IGFsbGVsZSIsIHg9IE5VTEwpCn0KCnBsdF9tZXRhIDwtIG1ldGFfZGYgJT4lIAogIGZpbHRlcihzYW1wbGUgPT0gc2FtcCkgJT4lIAogIHBsb3RfbWV0YV9vZGRzKGNlbGxfdHlwZSA9ICJjREMiLCBsb2N1cyA9ICJBIikKCnBsdF9tZXRhCmBgYApgYGB7ciwgZmlnLndpZHRoPTMsIGZpZy5oZWlnaHQ9M30KbWV0YV9kZiAlPiUgCiAgZmlsdGVyKHNhbXBsZSA9PSBzYW1wKSAlPiUKICBwbG90X21ldGFfb2RkcyhjZWxsX3R5cGUgPSAiY0RDIiwgbG9jdXMgPSAiRFJCMSIpCmBgYAoKCmBgYHtyLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD0zfQpzYW1wbGVzIDwtIHVuaXF1ZShtZXRhX2RmJHNhbXBsZSkKZm9yIChpIGluIDE6bGVuZ3RoKHNhbXBsZXMpKXsKcGx0X21ldGEgPC0gbWV0YV9kZiAlPiUgCiAgZmlsdGVyKHNhbXBsZSA9PSBzYW1wbGVzW2ldKSAlPiUgCiAgcGxvdF9tZXRhX29kZHMoY2VsbF90eXBlID0gIkNEMTQgTW9ub2N5dGUiLCBsb2N1cyA9ICJBIikgKwogIGdndGl0bGUoc2FtcGxlc1tpXSkKICBwcmludChwbHRfbWV0YSkKfQpgYGAKYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0ID0gMywgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQpwbHRfbWV0YV9hbGxMb2NpIDwtIG1ldGFfZGYgJT4lIAogIGZpbHRlcihzYW1wbGUgPT0gc2FtcCkgJT4lCiAgZmlsdGVyKGNlbGx0eXBlID09ICJjREMiKSAlPiUgCiAgbXV0YXRlKGdlbm90eXBlciA9IHJlZm9ybWF0X2hsYV9nZW5vdHlwZXIoZ2Vub3R5cGVyKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZ2Vub3R5cGVyLCB5ID0gVEUsIHltaW4gPSBsb3dlciwgeW1heCA9IHVwcGVyKSkrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fZXJyb3JiYXIod2lkdGggPSAwLjQpKwogIGZhY2V0X2dyaWQoLn5nZW5lKSsKICB0aGVtZV9idygpKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsTkEpKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgbGFicyh5ID0gIkxvZy1PZGRzIHJhdGlvXG5vZiBkb21pbmFudCBhbGxlbGUiLCB4PSBOVUxMKQoKcGx0X21ldGFfYWxsTG9jaSAgCmBgYAoKCgojIyMgTXVsdGktc2FtcGxlIGFuYWx5c2lzCgpgYGB7ciwgbWVzc2FnZSA9IEZ9Cm1ldGFfZGYgPC0gcmVhZF9jc3YoaGVyZSgiN19ITEFfQVNFL21ldGFfYW5hbHlzaXNfcmVzdWx0c19jMTIuY3N2IikpICU+JSAKICBtdXRhdGUoZ2Vub3R5cGVyID0gcmVmb3JtYXRfaGxhX2dlbm90eXBlcihnZW5vdHlwZXIpLAogICAgICAgICBjZWxsdHlwZSA9IGZhY3RvcihjZWxsdHlwZSwgbGV2ZWxzID0gYygKICAgICAgICAgICJjREMiLCAiQ0QxNCBNb25vY3l0ZSIsICJCIiwgInBEQyIsICJDRDE2IE1vbm9jeXRlIiwgIkNEOCBUIiwgIkNENCBUIiwgIk5LIikpKQpgYGAKCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodCA9IDYsIHdhcm5pbmcgPSBGfQptZXRhX2RmICU+JSAKICBnZ3Bsb3QoYWVzKHg9Y2VsbHR5cGUseT1URSwgZmlsbCA9IGNlbGx0eXBlKSkrCiAgZ2VvbV92aW9saW4oKSsKICBnZW9tX2ppdHRlcihhbHBoYSA9IDAuMiwgc2l6ZSA9IDAuMikrCiAgc3RhdF9zdW1tYXJ5KGZ1bj1tZWFuLCBzdGF0PSAicG9pbnQiKSsKICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBtZWFuX3NlLCBnZW9tPSJlcnJvcmJhciIpKwogIGZhY2V0X2dyaWQoZ2VuZX5nZW5vdHlwZXIpKwogIHRoZW1lX2J3KCkrCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIGxhYnMoeSA9ICJMb2ctT2RkcyByYXRpbyBvZiBkb21pbmFudCBhbGxlbGUiLCB4PSBOVUxMLCBmaWxsID0gIkNlbGwgdHlwZSIpICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikKCm1ldGFfZGYgJT4lIAogIGdncGxvdChhZXMoeD1nZW5vdHlwZXIseT1URSwgZmlsbCA9IGNlbGx0eXBlKSkrCiAgZ2VvbV92aW9saW4oKSsKICBnZW9tX2ppdHRlcihhbHBoYSA9IDAuMiwgc2l6ZSA9IDAuMikrCiAgc3RhdF9zdW1tYXJ5KGZ1bj1tZWFuLCBzdGF0PSAicG9pbnQiKSsKICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBtZWFuX3NlLCBnZW9tPSJlcnJvcmJhciIpKwogIGZhY2V0X2dyaWQoZ2VuZX5jZWxsdHlwZSkrCiAgdGhlbWVfYncoKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgbGFicyh5ID0gIkxvZy1PZGRzIHJhdGlvIG9mIGRvbWluYW50IGFsbGVsZSIsIHg9IE5VTEwsIGZpbGwgPSAiQ2VsbCB0eXBlIikgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKQpgYGAKCmBgYHtyfQogbWV0YV9kZiAlPiUgCiAgZmlsdGVyKHNhbXBsZSA9PSBzYW1wKSAlPiUKICBmaWx0ZXIoY2VsbHR5cGUgPT0gImNEQyIpICU+JSAKICBtdXRhdGUoZ2Vub3R5cGVyID0gcmVmb3JtYXRfaGxhX2dlbm90eXBlcihnZW5vdHlwZXIpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBnZW5vdHlwZXIsIHkgPSBURSwgeW1pbiA9IGxvd2VyLCB5bWF4ID0gdXBwZXIpKSsKICBnZW9tX3BvaW50KCkrCiAgZ2VvbV9lcnJvcmJhcih3aWR0aCA9IDAuNCkrCiAgZmFjZXRfZ3JpZCgufmdlbmUpKwogIHRoZW1lX2J3KCkrCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCxOQSkpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBsYWJzKHkgPSAiTG9nLU9kZHMgcmF0aW9cbm9mIGRvbWluYW50IGFsbGVsZSIsIHg9IE5VTEwpCmBgYAoKCiMjIyBDb3JyZWxhdGlvbiBhbmFseXNpcwoKYGBge3IsIG1lc3NhZ2UgPSBGLCB3YXJuaW5nPUZ9Cm1ldGFfZGYgJT4lIAogIGZpbHRlcihnZW5lID09ICJBIiwgY2VsbHR5cGUgPT0gImNEQyIpICU+JSAKICBzZWxlY3Qoc2FtcGxlLCBnZW5vdHlwZXIsIFRFKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9ICJnZW5vdHlwZXIiLCB2YWx1ZXNfZnJvbSA9ICJURSIpICU+JSAKICBzZWxlY3QoLXNhbXBsZSkgJT4lIAogIEdHYWxseTo6Z2dwYWlycyhwcm9ncmVzcyA9IEZBTFNFKSArCiAgdGhlbWVfYncoKQpgYGAKCmBgYHtyLCBtZXNzYWdlID0gRiwgd2FybmluZz1GfQphY2N1cmFjeV9kZiA8LSByZWFkUkRTKGhlcmUoIjNfRFJCL2lzYl9hY2N1cmFjeV9kcmIzNDVfZmlsdGVyZWQuUkRTIikpICU+JSAKICBtdXRhdGUoZ2Vub3R5cGVyID0gcmVmb3JtYXRfaGxhX2dlbm90eXBlcihnZW5vdHlwZXIpKSAlPiUgCiAgc2VsZWN0KHNhbXBsZSwgZ2VuZT1sb2N1cywgZ2Vub3R5cGVyLCBhY2N1cmFjeSkgJT4lIAogIGRpc3RpbmN0KCkKZm9yIChpIGluIGMoMCwxKSl7CiAgc3VwcHJlc3NXYXJuaW5ncyh7CiAgcGx0IDwtIG1ldGFfZGYgJT4lIAogICAgdW5ncm91cCgpICU+JSAKICAgIGZpbHRlcihnZW5lID09ICJBIiwgY2VsbHR5cGUgPT0gImNEQyIpICU+JSAKICAgIGxlZnRfam9pbihhY2N1cmFjeV9kZiwgYnkgPSBjKCJzYW1wbGUiLCAiZ2VuZSIsICJnZW5vdHlwZXIiKSkgJT4lIAogICAgZmlsdGVyKGFjY3VyYWN5ID09IGkgfCBnZW5vdHlwZXIgPT0gIkdyb3VuZCB0cnV0aCIpICU+JSAKICAgICMgZHJvcF9uYShhY2N1cmFjeSkgJT4lIAogICAgc2VsZWN0KHNhbXBsZSwgZ2Vub3R5cGVyLCBURSkgJT4lIAogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9ICJnZW5vdHlwZXIiLCB2YWx1ZXNfZnJvbSA9ICJURSIpICU+JSAKICAgIHNlbGVjdCgtc2FtcGxlKSAlPiUgCiAgICBHR2FsbHk6OmdncGFpcnMocHJvZ3Jlc3MgPSBGQUxTRSkgKwogICAgdGhlbWVfYncoKSArCiAgICBnZ3RpdGxlKHNwcmludGYoIkNvcnJlbGF0aW9uIG9mIGFsbGVsZSByYXRpb3Mgd2hlcmUgYWNjdXJhY3kgPSAlcyIsIGkpKQogIHByaW50KHBsdCkKICB9KQp9CmBgYAoKYGBge3IsIHdhcm5pbmcgPSBGfQpjb3JyX2RmIDwtIG1ldGFfZGYgJT4lIAogIG11dGF0ZShnZW5vdHlwZXIgPSByZWZvcm1hdF9obGFfZ2Vub3R5cGVyKGdlbm90eXBlcikpICU+JSAKICBzZWxlY3Qoc2FtcGxlLCBnZW5vdHlwZXIsIGNlbGx0eXBlLCBnZW5lLCBURSkgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSAiZ2Vub3R5cGVyIiwgdmFsdWVzX2Zyb20gPSAiVEUiKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGMoYXJjYXNITEEsIEhMQW1pbmVyLCBPcHRpVHlwZSwgUEhMQVQpLCBuYW1lc190byA9ICJnZW5vdHlwZXIiLCB2YWx1ZXNfdG8gPSAiVEUiKSAlPiUgCiAgbXV0YXRlKGdlbm90eXBlciA9IHJlZm9ybWF0X2hsYV9nZW5vdHlwZXIoZ2Vub3R5cGVyKSkKY29ycl9kZiAlPiUgCiAgZ2dwbG90KGFlcyh4PWBHcm91bmQgdHJ1dGhgLCB5PVRFKSkrCiAgZ2VvbV9wb2ludChzaXplID0gMC41KSsKICBmYWNldF9ncmlkKGdlbmUgfiBnZW5vdHlwZXIpICsKICB0aGVtZV9idygpICsKICBnZ3B1YnI6OnN0YXRfY29yKGFlcyhsYWJlbCA9IC4ucnIubGFiZWwuLiksIGxhYmVsLngubnBjID0gImxlZnQiLCBsYWJlbC55Lm5wYyA9ICJ0b3AiLCBnZW9tID0gImxhYmVsIikKYGBgCgpgYGB7cn0KZm9yIChpIGluIGMoMCwxKSl7CiAgc3VwcHJlc3NXYXJuaW5ncyh7CiAgcGx0IDwtIGNvcnJfZGYgJT4lIAogICAgdW5ncm91cCgpICU+JSAKICAgICMgZmlsdGVyKGdlbmUgPT0gIkEiLCBjZWxsdHlwZSA9PSAiY0RDIikgJT4lIAogICAgbGVmdF9qb2luKGFjY3VyYWN5X2RmLCBieSA9IGMoInNhbXBsZSIsICJnZW5lIiwgImdlbm90eXBlciIpKSAlPiUgCiAgICBmaWx0ZXIoYWNjdXJhY3kgPT0gaSkgJT4lIAogICAgZ2dwbG90KGFlcyh4PWBHcm91bmQgdHJ1dGhgLCB5PVRFKSkrCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjUpKwogICAgZmFjZXRfZ3JpZChnZW5lIH4gZ2Vub3R5cGVyKSArCiAgICB0aGVtZV9idygpICsKICAgIGdncHVicjo6c3RhdF9jb3IoYWVzKGxhYmVsID0gLi5yci5sYWJlbC4uKSwgbGFiZWwueC5ucGMgPSAibGVmdCIsIGxhYmVsLnkubnBjID0gInRvcCIsIGdlb20gPSAibGFiZWwiKSArCiAgICAgIGdndGl0bGUoc3ByaW50ZigiQ29ycmVsYXRpb24gb2YgYWxsZWxlIHJhdGlvcyB3aGVyZSBhY2N1cmFjeSA9ICVzIiwgaSkpICsKICAgIGxhYnMoeSA9ICJQcmVkaWN0ZWQgZ2Vub3R5cGUgSExBIGFsbGVsZSBsb2ctb2RkcyByYXRpbyIsIHggPSAiR3JvdW5kIHRydXRoIGdlbm90eXBlIEhMQSBhbGxlbGUgbG9nLW9kZHMgcmF0aW8iKQogIGFzc2lnbihzcHJpbnRmKCJwbHRfbWV0YV9jb3JyXyVzIiwgaSksIHBsdCkKICBwcmludChwbHQpCiAgfSkKfQoKYGBgCmBgYHtyfQpwbHRfbWV0YV9jb3JyX2FiYnJldiA8LSBjb3JyX2RmICU+JSAKICBsZWZ0X2pvaW4oYWNjdXJhY3lfZGYsIGJ5ID0gYygic2FtcGxlIiwgImdlbmUiLCAiZ2Vub3R5cGVyIikpICU+JSAKICBmaWx0ZXIoZ2VuZSA9PSAiQSIsIGFjY3VyYWN5ICVpbiUgYygwLDAuNSwxKSkgJT4lCiAgZ2dwbG90KGFlcyh4PWBHcm91bmQgdHJ1dGhgLCB5PVRFKSkrCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjUpKwogICAgZmFjZXRfZ3JpZChhY2N1cmFjeSB+IGdlbm90eXBlciwgbGFiZWxsZXIgPSBsYWJlbGxlcihhY2N1cmFjeSA9IGZ1bmN0aW9uKHgpIHNwcmludGYoIkFjY3VyYWN5OiAlcyIsIHgpKSkgKwogICAgdGhlbWVfYncoKSArCiAgICBnZ3B1YnI6OnN0YXRfY29yKGFlcyhsYWJlbCA9IC4ucnIubGFiZWwuLiksIGxhYmVsLngubnBjID0gImxlZnQiLCBsYWJlbC55Lm5wYyA9ICJ0b3AiLCBnZW9tID0gImxhYmVsIiwgbWV0aG9kID0gInBlYXJzb24iKSArCiAgICBsYWJzKHkgPSAiTG9nLW9kZHMgcmF0aW8gdXNpbmcgcHJlZGljdGVkIGdlbm90eXBlIiwgeCA9ICJMb2ctb2RkcyByYXRpbyB1c2luZyBncm91bmQgdHJ1dGggZ2Vub3R5cGVyIikKcGx0X21ldGFfY29ycl9hYmJyZXYKYGBgCmBgYHtyfQphY2N1cmFjeV9kZiAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGNvdW50KGdlbmUsIGdlbm90eXBlciwgYWNjdXJhY3kpCmBgYAoKCgojIyMgQnkgc2V2ZXJpdHkKCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodCA9IDYsIHdhcm5pbmcgPSBGfQptZXRhX2RmICU+JSAKICBmaWx0ZXIoZ2Vub3R5cGVyID09ICJHcm91bmQgdHJ1dGgiKSAlPiUgCiAgbGVmdF9qb2luKAogICAgc3J0ICU+JSAKICAgICAgc2VsZWN0KHNhbXBsZSA9IHNhbXBsZUlELCBzZXZlcml0eSkgJT4lIAogICAgICBkaXN0aW5jdCgpLAogICAgYnkgPSAic2FtcGxlIgogICkgJT4lIAogIGdncGxvdChhZXMoeD1zZXZlcml0eSx5PVRFLCBmaWxsID0gY2VsbHR5cGUpKSsKICAgIGdlb21fdmlvbGluKCkrCiAgICBnZW9tX2ppdHRlcihhbHBoYSA9IDAuMiwgc2l6ZSA9IDAuMikrCiAgICBzdGF0X3N1bW1hcnkoZnVuPW1lYW4sIHN0YXQ9ICJwb2ludCIpKwogICAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gbWVhbl9zZSwgZ2VvbT0iZXJyb3JiYXIiKSsKICAgIGZhY2V0X2dyaWQoZ2VuZX5jZWxsdHlwZSkrCiAgICB0aGVtZV9idygpKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogICAgbGFicyh5ID0gIkxvZy1PZGRzIHJhdGlvIG9mIGRvbWluYW50IGFsbGVsZSIsIHg9IE5VTEwsIGZpbGwgPSAiQ2VsbCB0eXBlIikgKwogICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIpCmBgYAoKYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0ID0gNiwgd2FybmluZyA9IEZ9Cm1ldGFfZGYgJT4lIAogIGZpbHRlcihnZW5vdHlwZXIgPT0gIkdyb3VuZCB0cnV0aCIpICU+JSAKICBsZWZ0X2pvaW4oCiAgICBzcnQgJT4lIAogICAgICBzZWxlY3Qoc2FtcGxlID0gc2FtcGxlSUQsIHNldmVyaXR5KSAlPiUgCiAgICAgIGRpc3RpbmN0KCksCiAgICBieSA9ICJzYW1wbGUiCiAgKSAlPiUgCiAgbXV0YXRlKHNldmVyaXR5ID0gYXMubnVtZXJpYyhzZXZlcml0eSkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzZXZlcml0eSwgeSA9IFRFKSkgKwogICMgZ2VvbV9wb2ludCgpICsgCiAgc3RhdF9zdW1tYXJ5KGZ1bj1tZWFuLCBzdGF0PSAicG9pbnQiLCBzaXplID0gMC4yKSsKICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBtZWFuX3NlLCBnZW9tPSJlcnJvcmJhciIsIHNpemUgPSAwLjIpKwogIHN0YXRfc21vb3RoKG1ldGhvZCA9ICJsbSIpKwogIGZhY2V0X2dyaWQoY2VsbHR5cGV+Z2VuZSkrCiAgdGhlbWVfYncoKSAKYGBgCgojIFBsb3RzIGZvciBmaWd1cmVzCgojIEFzc2VtYmxlIHBsb3QKYGBge3IsIGZpZy53aWR0aCA9IDE0LCBmaWcuaGVpZ2h0ID0gMTB9CiMgcGx0X2FsbGVsZV9mcmVxX2xnZCA8LSBjb3dwbG90OjpnZXRfbGVnZW5kKHBsdF9hbGxlbGVfZnJlcSkKIyBwbHRfbWF4X2FsbGVsZV9sZ2QgPC0gY293cGxvdDo6Z2V0X2xlZ2VuZChwbHRfbWF4X2FsbGVsZSkKY29sXzEgPC0gcGxvdF9ncmlkKAogIHBsdF9hbGxlbGVfZnJlcSwKICBwbHRfbWF4X2FsbGVsZSwKICBuY29sID0gMSwKICByZWxfaGVpZ2h0cyA9IGMoNSwzKSwKICBhbGlnbiA9ICJ2IiwgYXhpcyA9ICJsciIsCiAgbGFiZWxzID0gTEVUVEVSU1sxOjJdCikKCmNvbF8yIDwtIHBsb3RfZ3JpZCgKICBwbHRfc3J0LAogIHBsdF9tZXRhLAogIG5jb2wgPSAxLAogIGFsaWduID0gInYiLCBheGlzID0gImxyIiwKICBsYWJlbHMgPSBMRVRURVJTWzM6NF0sCiAgaGp1c3QgPSAwLjUKKQpyb3dfMSA8LSBwbG90X2dyaWQoCiAgY29sXzEsCiAgY29sXzIsCiAgbnJvdyA9IDEsCiAgcmVsX3dpZHRocyA9IGMoNiwzKQopCnJvd18yIDwtIHBsb3RfZ3JpZCgKICBwbHRfbWV0YV9jb3JyXzAgK2dndGl0bGUoTlVMTCksCiAgcGx0X21ldGFfY29ycl8xICtnZ3RpdGxlKE5VTEwpLAogIGxhYmVscyA9IExFVFRFUlNbNTo2XSwKICBuY29sID0gMgopCnBsb3RfZ3JpZCgKICByb3dfMSwKICByb3dfMiwKICByZWxfaGVpZ2h0cyA9IGMoMywyKSwKICBuY29sID0gMQopCmBgYAoKYGBge3IsIGZpZy53aWR0aCA9IDE0LCBmaWcuaGVpZ2h0ID0gNn0KY29sXzEgPC0gcGxvdF9ncmlkKAogIHBsdF9zcnQsCiAgcGx0X21ldGEsCiAgbmNvbCA9IDEsCiAgYWxpZ24gPSAidiIsIGF4aXMgPSAibHIiLAogIGxhYmVscyA9IExFVFRFUlNbYygxLDMpXSwKICBsYWJlbF94ID0gLTAuMDUKKQoKY29sXzIgPC0gcGxvdF9ncmlkKAogIHBsdF9tYXhfYWxsZWxlLAogIHBsdF9tZXRhX2NvcnJfYWJicmV2LAogIG5jb2wgPSAxLAogIHJlbF9oZWlnaHRzID0gYygzLDUpLAogIGFsaWduID0gInYiLCBheGlzID0gImxyIiwKICBsYWJlbHMgPSBMRVRURVJTW2MoMiw0KV0sCiAgbGFiZWxfeCA9IC0wLjA1CikKCnBsdF9maWdfbWFpbiA8LSBwbG90X2dyaWQoCiAgTlVMTCwKICBjb2xfMSwKICBjb2xfMiwKICBucm93ID0gMSwKICByZWxfd2lkdGhzID0gYygwLjI1LDMsNikKKQoKcGx0X2ZpZ19tYWluCmBgYAoKYGBge3IsIGZpZy53aWR0aCA9IDE0LCBmaWcuaGVpZ2h0ID0gNX0KY29sXzEgPC0gcGxvdF9ncmlkKAogIHBsdF9zcnQsCiAgcGx0X21ldGErIGxhYnMoeT0iTG9nLW9kZHMgcmF0aW9cbm9mIGRvbWluYW50IGFsbGVsZSIpLAogIG5jb2wgPSAxLAogIGFsaWduID0gInYiLCBheGlzID0gImxyIiwKICBsYWJlbHMgPSBMRVRURVJTW2MoMSwzKV0sCiAgbGFiZWxfeCA9IC0wLjA1CikKCmNvbF8yIDwtIHBsb3RfZ3JpZCgKICBwbHRfbWF4X2FsbGVsZSwKICBwbHRfbWV0YV9jb3JyX2FiYnJldiArIGZhY2V0X2dyaWQoLiB+IGdlbm90eXBlcikgKyBsYWJzKHk9IkxvZy1vZGRzIHJhdGlvIHVzaW5nXG5wcmVkaWN0ZWQgZ2Vub3R5cGUiKSwKICBuY29sID0gMSwKICByZWxfaGVpZ2h0cyA9IGMoMSwxKSwKICBhbGlnbiA9ICJ2IiwgYXhpcyA9ICJsciIsCiAgbGFiZWxzID0gTEVUVEVSU1tjKDIsNCldLAogIGxhYmVsX3ggPSAtMC4wNQopCgpwbHRfZmlnX21haW4gPC0gcGxvdF9ncmlkKAogIE5VTEwsCiAgY29sXzEsCiAgTlVMTCwKICBjb2xfMiwKICBucm93ID0gMSwKICByZWxfd2lkdGhzID0gYygwLjI1LDMsMC4yNSw2KQopCgpwbHRfZmlnX21haW4KYGBgCgpgYGB7cn0Kc2F2ZV9wbG90KGhlcmUoImZpZ3VyZXNfcGRmL3YyLzdfc2NITEEucGRmIiksIHBsdF9maWdfbWFpbiwgYmFzZV9oZWlnaHQgPSA1LCBiYXNlX3dpZHRoID0gMTQpCmBgYAoKYGBge3IsIGZpZy53aWR0aCA9IDYsIGZpZy5oZWlnaHQ9NX0KcGx0X2ZpZ19zdXBwIDwtIHBsdF9tZXRhX2NvcnJfYWJicmV2ICsgZmFjZXRfZ3JpZChhY2N1cmFjeSB+IGdlbm90eXBlciwgbWFyZ2lucyA9ICJhY2N1cmFjeSIpIApwbHRfZmlnX3N1cHAKYGBgCmBgYHtyfQpzYXZlX3Bsb3QoaGVyZSgiZmlndXJlc19wZGYvdjIvczhfQVNFX2NvcnJlbGF0aW9uLnBkZiIpLCBwbHRfZmlnX3N1cHAsIGJhc2VfaGVpZ2h0ID0gNSwgYmFzZV93aWR0aCA9IDYpCmBgYApgYGB7ciwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTEyfQpwbHRfZmlnX3N1cHBfYWxsTG9jaSA8LSBwbG90X2dyaWQoCiAgcGx0X21heF9hbGxlbGVfYWxsR2VuZXNUeXBlcnMsCiAgcGx0X21ldGFfYWxsTG9jaSwKICBuY29sID0gMSwKICByZWxfaGVpZ2h0cyA9IGMoMC44LDAuMiksIAogIGFsaWduID0gInYiLAogIGF4aXMgPSAibHIiLAogIGxhYmVscyA9IExFVFRFUlNbMToyXQopCgpwbHRfZmlnX3N1cHBfYWxsTG9jaQpgYGAKYGBge3J9CnNhdmVfcGxvdChoZXJlKCJmaWd1cmVzX3BkZi92Mi9zN19BU0VfYWxsTG9jaS5wZGYiKSwgcGx0X2ZpZ19zdXBwX2FsbExvY2ksIGJhc2VfaGVpZ2h0ID0gMTAsIGJhc2Vfd2lkdGggPSAxMikKYGBgCgojIFNhdmUgYWxsIGZpZ3VyZSBvYmplY3RzIApgYGB7cn0KbGlzdE4gPC0gZnVuY3Rpb24oLi4uKSB7CiAgYW5vbkxpc3QgPC0gbGlzdCguLi4pCiAgbmFtZXMoYW5vbkxpc3QpIDwtIGFzLmNoYXJhY3RlcihzdWJzdGl0dXRlKGxpc3QoLi4uKSkpWy0xXQogIGFub25MaXN0Cn0KCnNhdmVSRFMoCiAgbGlzdE4ocGx0X3NydCwKICAgICAgICBwbHRfbWV0YSwKICAgICAgICBwbHRfbWF4X2FsbGVsZSwKICAgICAgICBwbHRfbWV0YV9jb3JyX2FiYnJldgogICAgICAgICksCiAgaGVyZSgiZmlndXJlc19vYmplY3QvN19zY0hMQV9vYmplY3RzLlJEUyIpCikKYGBgCgojIE9sZCB3b3JrCgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBzY19tZXRhIDwtIGZ1bmN0aW9uKGRmKXsgLS0+CjwhLS0gICBtIDwtIG1ldGFiaW4oZXZlbnQuZSA9IG9ic2VydmVkLCBuLmUgPSBnZW5lX3N1bV90eXBlZCwgZXZlbnQuYyA9IGV4cGVjdGVkLCBuLmMgPSBnZW5lX3N1bV90eXBlZCwgLS0+CjwhLS0gICAgICAgICBkYXRhID0gZGYsIC0tPgo8IS0tICAgICAgICAgbWV0aG9kID0gIkludmVyc2UiLCAtLT4KPCEtLSAgICAgICAgIGluY3IgPSAwLjEsIC0tPgo8IS0tICAgICAgICAgc20gPSAiT1IiKSAtLT4KPCEtLSAgIGRhdGEuZnJhbWUoc3VtbWFyeShtKSRyYW5kb20pICU+JSAgLS0+CjwhLS0gICAgIHNlbGVjdChURSwgc2VURSwgbG93ZXIsIHVwcGVyKSAlPiUgIC0tPgo8IS0tICAgICBtdXRhdGVfYWxsKGV4cCkgLS0+CjwhLS0gfSAtLT4KPCEtLSBgYGAgLS0+CgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gc2FtcCA8LSAiSU5DT1YxWzAtMl1bMC05XS1CTCIgLS0+CjwhLS0geCA8LSB0aWJibGUoZ2Vub3R5cGVyID0gYygiaW52aXRybyIsICJhcmNhc0hMQSIsICJvcHRpdHlwZSIsICJwaGxhdCIsICJobGFtaW5lciIpKSAlPiUgIC0tPgo8IS0tICAgbXV0YXRlKGRhdGEgPSBtYXAoZ2Vub3R5cGVyLCBmdW5jdGlvbih4KSBzdXBwcmVzc01lc3NhZ2VzKHJlYWRfdHN2KCIuLi8uLi9jb3ZpZC9pc2Ivc2NITEFjb3VudC9CTF9mYXN0cV9maWxlcy50eHQiLCBjb2xfbmFtZXMgPSAic2FtcGxlIikpKSkgJT4lICAtLT4KPCEtLSAgIHVubmVzdChkYXRhKSAlPiUgIC0tPgo8IS0tICAgZmlsdGVyKGdyZXBsKHNhbXAsIHNhbXBsZSkpICU+JSAgLS0+CjwhLS0gICAjIEltcG9ydCBkYXRhIGJhc2VkIG9uIHNhbXBsZSBhbmQgZ2Vub3R5cGVyIC0tPgo8IS0tICAgbXV0YXRlKHJlc3VsdF9wYXRoID0gc3ByaW50ZigiJXMvb3V0cHV0LyVzIixzY0hMQWNvdW50X2RpciwgZ2Vub3R5cGVyKSwgLS0+CjwhLS0gICAgICAgICAgYmFyY29kZV9wYXRoID0gc3ByaW50ZigiJXMvYmFyY29kZXMiLCBzY0hMQWNvdW50X2RpcikpICU+JSAgLS0+CjwhLS0gICAjIGhlYWQoMikgJT4lIC0tPgo8IS0tICAgbXV0YXRlKGRhdGEgPSBwbWFwKGxpc3Qoc2FtcGxlLCByZXN1bHRfcGF0aCwgYmFyY29kZV9wYXRoKSwgZnVuY3Rpb24ocyxyLGIpeyAtLT4KPCEtLSAgICAgc2NITEFfZGF0YV9wcm9jZXNzaW5nKCAtLT4KPCEtLSAgICAgICBzYW1wbGU9cywgLS0+CjwhLS0gICAgICAgcmVzdWx0X2Rpcj1yLCAtLT4KPCEtLSAgICAgICBiYXJjb2RlX2Rpcj1iIC0tPgo8IS0tICAgICApIC0tPgo8IS0tICAgfSkpICU+JSB1bm5lc3QoZGF0YSkgLS0+CjwhLS0geCAtLT4KPCEtLSB5IDwtIHggJT4lICAtLT4KPCEtLSAgIGZpbHRlcihjZWxsICVpbiUgY2VsbF9saXN0KSAlPiUgIC0tPgo8IS0tICAgbXV0YXRlKHNhbXBsZSA9IGdzdWIoIl9bQS1aXVswLTldJCIsIiIsc2FtcGxlKSkgJT4lICAtLT4KPCEtLSAgICMgIyBmaWx0ZXIobl9hbGxlbGVzX29ic2VydmVkID09IDIsIGdyZXBsKCJeRFtQUVJdIiwgZ2VuZSksIHNhbXBsZUlEICVpbiUgYygiSU5DT1YwMDMtQUMiLCAiSU5DT1YwMjQtQUMiKSkgJT4lICAtLT4KPCEtLSAgICMgc2VsZWN0KGNlbGwsIGxvY3VzLCBjb3VudCwgZ2VuZV9zdW1fdHlwZWQsIGNlbGx0eXBlKSAlPiUgIC0tPgo8IS0tICAgIyBncm91cF9ieShzZXZlcml0eSwgY2VsbHR5cGUsIGdlbmUpICU+JSAgLS0+CjwhLS0gICBmaWx0ZXIoZ2VuZSA9PSAiQSIpICU+JSAgLS0+CjwhLS0gICBncm91cF9ieShzYW1wbGUsIGdlbm90eXBlcikgJT4lICAtLT4KPCEtLSAgIHNhbXBsZV9uKDUwMCwgcmVwbGFjZSA9IFQpICU+JSAtLT4KPCEtLSAgIG11dGF0ZShjb21wbGVtZW50ID0gZ2VuZV9zdW1fdHlwZWQgLSBjb3VudCwgZXhwZWN0ZWQgPSAwLjUqZ2VuZV9zdW1fdHlwZWQpICU+JSAgLS0+CjwhLS0gICByb3d3aXNlKCkgJT4lICAtLT4KPCEtLSAgIG11dGF0ZShvYnNlcnZlZCA9IG1heChhY3Jvc3MoYyhjb3VudCwgY29tcGxlbWVudCkpKSkgJT4lICAtLT4KPCEtLSAgIGdyb3VwX2J5KHNhbXBsZSwgZ2Vub3R5cGVyKSAlPiUgIC0tPgo8IS0tICAgbmVzdCgpICU+JSAgLS0+CjwhLS0gICBtdXRhdGUoZGF0YSA9IG1hcChkYXRhLCBzY19tZXRhKSkgJT4lICAtLT4KPCEtLSAgIHVubmVzdChkYXRhKSAtLT4KPCEtLSBgYGAgLS0+Cgo8IS0tIGBgYHtyLCBmaWcud2lkdGggPSAyNCwgZmlnLmhlaWdodCA9IDR9IC0tPgo8IS0tIHkgJT4lIC0tPgo8IS0tICAgbXV0YXRlKGdlbm90eXBlciA9IGZhY3RvcihnZW5vdHlwZXIsIGxldmVscyA9IGMoImhsYW1pbmVyIiwicGhsYXQiLCJvcHRpdHlwZSIsImFyY2FzSExBIiwiaW52aXRybyIpKSkgJT4lICAtLT4KPCEtLSAgIGdncGxvdChhZXMoeCA9IGdlbm90eXBlciwgeSA9IFRFLCB5bWluID0gbG93ZXIsIHltYXggPSB1cHBlcikpKyAtLT4KPCEtLSAgIGdlb21fcG9pbnQoKSsgLS0+CjwhLS0gICBnZW9tX2Vycm9yYmFyKCkrIC0tPgo8IS0tICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIikrIC0tPgo8IS0tICAgZmFjZXRfZ3JpZCgufnNhbXBsZSwgc2NhbGVzID0gImZyZWUiKSsgLS0+CjwhLS0gICB0aGVtZV9idygpKyAtLT4KPCEtLSAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSArIC0tPgo8IS0tICAgY29vcmRfZmxpcCgpICsgLS0+CjwhLS0gICBsYWJzKHkgPSAiT2RkcyByYXRpbyBvZiBkb21pbmFudCBhbGxlbGUiLCB4PSBOVUxMKSAtLT4KPCEtLSBgYGAgLS0+CgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gc2FtcCA8LSAiSU5DT1YwNjktQkwiIC0tPgo8IS0tIGNlbGxfbGlzdCA8LSBzcnQgJT4lIGZpbHRlcihjZWxsdHlwZSA9PSAiY0RDIikgJT4lIHB1bGwoY2VsbCkgLS0+CjwhLS0geCA8LSB0aWJibGUoZ2Vub3R5cGVyID0gYygiaW52aXRybyIsICJhcmNhc0hMQSIsICJvcHRpdHlwZSIsICJwaGxhdCIsICJobGFtaW5lciIpKSAlPiUgIC0tPgo8IS0tICAgbXV0YXRlKGRhdGEgPSBtYXAoZ2Vub3R5cGVyLCBmdW5jdGlvbih4KSBzdXBwcmVzc01lc3NhZ2VzKHJlYWRfdHN2KCIuLi8uLi9jb3ZpZC9pc2Ivc2NITEFjb3VudC9CTF9mYXN0cV9maWxlcy50eHQiLCBjb2xfbmFtZXMgPSAic2FtcGxlIikpKSkgJT4lICAtLT4KPCEtLSAgIHVubmVzdChkYXRhKSAlPiUgIC0tPgo8IS0tICAgZmlsdGVyKGdyZXBsKHNhbXAsIHNhbXBsZSkpICU+JSAgLS0+CjwhLS0gICAjIEltcG9ydCBkYXRhIGJhc2VkIG9uIHNhbXBsZSBhbmQgZ2Vub3R5cGVyIC0tPgo8IS0tICAgbXV0YXRlKHJlc3VsdF9wYXRoID0gc3ByaW50ZigiJXMvb3V0cHV0LyVzIixzY0hMQWNvdW50X2RpciwgZ2Vub3R5cGVyKSwgLS0+CjwhLS0gICAgICAgICAgYmFyY29kZV9wYXRoID0gc3ByaW50ZigiJXMvYmFyY29kZXMiLCBzY0hMQWNvdW50X2RpcikpICU+JSAgLS0+CjwhLS0gICAjIGhlYWQoMikgJT4lIC0tPgo8IS0tICAgbXV0YXRlKGRhdGEgPSBwbWFwKGxpc3Qoc2FtcGxlLCByZXN1bHRfcGF0aCwgYmFyY29kZV9wYXRoKSwgZnVuY3Rpb24ocyxyLGIpeyAtLT4KPCEtLSAgICAgc2NITEFfZGF0YV9wcm9jZXNzaW5nKCAtLT4KPCEtLSAgICAgICBzYW1wbGU9cywgLS0+CjwhLS0gICAgICAgcmVzdWx0X2Rpcj1yLCAtLT4KPCEtLSAgICAgICBiYXJjb2RlX2Rpcj1iIC0tPgo8IS0tICAgICApIC0tPgo8IS0tICAgfSkpICU+JSB1bm5lc3QoZGF0YSkgLS0+CjwhLS0geSA8LSB4ICU+JSAgLS0+CjwhLS0gICBmaWx0ZXIoY2VsbCAlaW4lIGNlbGxfbGlzdCkgJT4lICAtLT4KPCEtLSAgIG11dGF0ZShzYW1wbGUgPSBnc3ViKCJfW0EtWl1bMC05XSQiLCIiLHNhbXBsZSkpICU+JSAgLS0+CjwhLS0gICBmaWx0ZXIoZ2VuZSA9PSAiQSIpICU+JSAgLS0+CjwhLS0gICBncm91cF9ieShzYW1wbGUsIGdlbm90eXBlcikgJT4lICAtLT4KPCEtLSAgIHNhbXBsZV9uKDUwMCwgcmVwbGFjZSA9IFQpICU+JSAtLT4KPCEtLSAgIG11dGF0ZShjb21wbGVtZW50ID0gZ2VuZV9zdW1fdHlwZWQgLSBjb3VudCwgZXhwZWN0ZWQgPSAwLjUqZ2VuZV9zdW1fdHlwZWQpICU+JSAgLS0+CjwhLS0gICByb3d3aXNlKCkgJT4lICAtLT4KPCEtLSAgIG11dGF0ZShvYnNlcnZlZCA9IG1heChhY3Jvc3MoYyhjb3VudCwgY29tcGxlbWVudCkpKSkgJT4lICAtLT4KPCEtLSAgIGdyb3VwX2J5KHNhbXBsZSwgZ2Vub3R5cGVyKSAlPiUgIC0tPgo8IS0tICAgbmVzdCgpICU+JSAgLS0+CjwhLS0gICBtdXRhdGUoZGF0YSA9IG1hcChkYXRhLCBzY19tZXRhKSkgJT4lICAtLT4KPCEtLSAgIHVubmVzdChkYXRhKSAtLT4KPCEtLSBwbHRfbWV0YSA8LSB5ICU+JSAgLS0+CjwhLS0gICB1bmdyb3VwKCkgJT4lICAtLT4KPCEtLSAgIG11dGF0ZShnZW5vdHlwZXIgPSByZWZvcm1hdF9obGFfZ2Vub3R5cGVyKGdlbm90eXBlcikpICU+JSAgLS0+CjwhLS0gICBnZ3Bsb3QoYWVzKHggPSBnZW5vdHlwZXIsIHkgPSBURSwgeW1pbiA9IGxvd2VyLCB5bWF4ID0gdXBwZXIpKSsgLS0+CjwhLS0gICBnZW9tX3BvaW50KCkrIC0tPgo8IS0tICAgZ2VvbV9lcnJvcmJhcigpKyAtLT4KPCEtLSAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEsIGxpbmV0eXBlID0gImRhc2hlZCIpKyAtLT4KPCEtLSAgIHRoZW1lX2J3KCkrIC0tPgo8IS0tICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKyAtLT4KPCEtLSAgIGxhYnMoeSA9ICJPZGRzIHJhdGlvIG9mIGRvbWluYW50IGFsbGVsZSIsIHg9IE5VTEwpIC0tPgo8IS0tIHBsdF9tZXRhICAgLS0+CjwhLS0gYGBgIC0tPgo8IS0tICMjIyBBbGwgY2x1c3RlcnMgLS0+Cgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBzYW1wIDwtICJJTkNPVjA2OS1CTCIgLS0+CjwhLS0gY2VsbF9saXN0IDwtIHNydCAlPiUgZmlsdGVyKGNlbGx0eXBlID09ICJjREMiKSAlPiUgcHVsbChjZWxsKSAtLT4KPCEtLSB4IDwtIHRpYmJsZShnZW5vdHlwZXIgPSBjKCJpbnZpdHJvIiwgImFyY2FzSExBIiwgIm9wdGl0eXBlIiwgInBobGF0IiwgImhsYW1pbmVyIikpICU+JSAgLS0+CjwhLS0gICBtdXRhdGUoZGF0YSA9IG1hcChnZW5vdHlwZXIsIGZ1bmN0aW9uKHgpIHN1cHByZXNzTWVzc2FnZXMocmVhZF90c3YoIi4uLy4uL2NvdmlkL2lzYi9zY0hMQWNvdW50L0JMX2Zhc3RxX2ZpbGVzLnR4dCIsIGNvbF9uYW1lcyA9ICJzYW1wbGUiKSkpKSAlPiUgIC0tPgo8IS0tICAgdW5uZXN0KGRhdGEpICU+JSAgLS0+CjwhLS0gICBmaWx0ZXIoZ3JlcGwoc2FtcCwgc2FtcGxlKSkgJT4lICAtLT4KPCEtLSAgICMgSW1wb3J0IGRhdGEgYmFzZWQgb24gc2FtcGxlIGFuZCBnZW5vdHlwZXIgLS0+CjwhLS0gICBtdXRhdGUocmVzdWx0X3BhdGggPSBzcHJpbnRmKCIlcy9vdXRwdXQvJXMiLHNjSExBY291bnRfZGlyLCBnZW5vdHlwZXIpLCAtLT4KPCEtLSAgICAgICAgICBiYXJjb2RlX3BhdGggPSBzcHJpbnRmKCIlcy9iYXJjb2RlcyIsIHNjSExBY291bnRfZGlyKSkgJT4lICAtLT4KPCEtLSAgICMgaGVhZCgyKSAlPiUgLS0+CjwhLS0gICBtdXRhdGUoZGF0YSA9IHBtYXAobGlzdChzYW1wbGUsIHJlc3VsdF9wYXRoLCBiYXJjb2RlX3BhdGgpLCBmdW5jdGlvbihzLHIsYil7IC0tPgo8IS0tICAgICBzY0hMQV9kYXRhX3Byb2Nlc3NpbmcoIC0tPgo8IS0tICAgICAgIHNhbXBsZT1zLCAtLT4KPCEtLSAgICAgICByZXN1bHRfZGlyPXIsIC0tPgo8IS0tICAgICAgIGJhcmNvZGVfZGlyPWIgLS0+CjwhLS0gICAgICkgLS0+CjwhLS0gICB9KSkgJT4lIHVubmVzdChkYXRhKSAtLT4KPCEtLSByZXNhbXBsZV9kZXB0aCA8LSA1MDAgLS0+CjwhLS0geSA8LSB4ICU+JSAgLS0+CjwhLS0gICBsZWZ0X2pvaW4oc3J0ICU+JSBzZWxlY3QoY2VsbHR5cGUsIGNlbGwpLCBieSA9ICJjZWxsIikgJT4lICAtLT4KPCEtLSAgIG11dGF0ZShzYW1wbGUgPSBnc3ViKCJfW0EtWl1bMC05XSQiLCIiLHNhbXBsZSkpICU+JSAgLS0+CjwhLS0gICAjIGZpbHRlcihnZW5lID09ICJBIikgJT4lICAtLT4KPCEtLSAgIGZpbHRlcighaXMubmEoY2VsbHR5cGUpKSAlPiUgIC0tPgo8IS0tICAgdW5pdGUoImdyb3VwIiwgY2VsbHR5cGUsIGdlbmUsIHNlcCA9ICJfIiwgcmVtb3ZlID0gRikgJT4lICAtLT4KPCEtLSAgICMgbXV0YXRlKGdyb3VwID0gY2VsbHR5cGUpICU+JSAgLS0+CjwhLS0gICBncm91cF9ieShncm91cCkgJT4lIG5lc3QoKSAlPiUgIC0tPgo8IS0tICAgbXV0YXRlKGRhdGEgPSBtYXAoZGF0YSwgZnVuY3Rpb24oeCl7IC0tPgo8IS0tICAgICB4ICU+JSAgLS0+CjwhLS0gICAgICAgZ3JvdXBfYnkoc2FtcGxlLCBnZW5vdHlwZXIpICU+JSAgLS0+CjwhLS0gICAgICAgIyBzYW1wbGVfbihyZXNhbXBsZV9kZXB0aCwgcmVwbGFjZSA9IFQpICU+JSAgLS0+CjwhLS0gICAgICAgbXV0YXRlKGNvbXBsZW1lbnQgPSBnZW5lX3N1bV90eXBlZCAtIGNvdW50LCBleHBlY3RlZCA9IDAuNSpnZW5lX3N1bV90eXBlZCkgJT4lICAtLT4KPCEtLSAgICAgICByb3d3aXNlKCkgJT4lICAtLT4KPCEtLSAgICAgICBtdXRhdGUob2JzZXJ2ZWQgPSBtYXgoYWNyb3NzKGMoY291bnQsIGNvbXBsZW1lbnQpKSkpICU+JSAgLS0+CjwhLS0gICAgICAgZ3JvdXBfYnkoc2FtcGxlLCBnZW5vdHlwZXIpICU+JSAgLS0+CjwhLS0gICAgICAgbmVzdCgpICU+JSAgLS0+CjwhLS0gICAgICAgbXV0YXRlKGRhdGEgPSBtYXAoZGF0YSwgc2NfbWV0YSkpICU+JSAgLS0+CjwhLS0gICAgICAgdW5uZXN0KGRhdGEpIC0tPgo8IS0tICAgfSkpICU+JSAgLS0+CjwhLS0gICB1bm5lc3QoZGF0YSkgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0ID0gNH0gLS0+CjwhLS0geSA8LSB5ICU+JSAgLS0+CjwhLS0gICBzZXBhcmF0ZShncm91cCwgaW50byA9IGMoImNlbGx0eXBlIiwgImdlbmUiKSwgc2VwID0gIl8iKSAlPiUgIC0tPgo8IS0tICAgbXV0YXRlKGdyb3VwID0gZmFjdG9yKGNlbGx0eXBlLCBsZXZlbHMgPSBjKCAtLT4KPCEtLSAgICAgImNEQyIsICJDRDE0IE1vbm9jeXRlIiwgIkIiLCAicERDIiwgIkNEMTYgTW9ub2N5dGUiLCAiQ0Q4IFQiLCAiQ0Q0IFQiLCAiTksiIC0tPgo8IS0tICAgKSkpIC0tPgo8IS0tIHkgJT4lICAtLT4KPCEtLSAgIHVuZ3JvdXAoKSAlPiUgIC0tPgo8IS0tICAgbXV0YXRlKGdlbm90eXBlciA9IHJlZm9ybWF0X2hsYV9nZW5vdHlwZXIoZ2Vub3R5cGVyKSkgJT4lICAtLT4KPCEtLSAgIGdncGxvdChhZXMoeCA9IGdlbm90eXBlciwgeSA9IFRFLCB5bWluID0gbG93ZXIsIHltYXggPSB1cHBlciwgZmlsbCA9IGdyb3VwKSkrIC0tPgo8IS0tICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC4yNSkrIC0tPgo8IS0tICAgZ2VvbV9lcnJvcmJhcihwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuOSksIHdpZHRoID0wLjUpKyAtLT4KPCEtLSAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEsIGxpbmV0eXBlID0gImRhc2hlZCIpKyAtLT4KPCEtLSAgIHRoZW1lX2J3KCkrIC0tPgo8IS0tICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKyAtLT4KPCEtLSAgIGxhYnMoeSA9ICJPZGRzIHJhdGlvIG9mIGRvbWluYW50IGFsbGVsZSIsIHg9IE5VTEwpICsgLS0+CjwhLS0gICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikgLS0+Cgo8IS0tIHkgJT4lICAtLT4KPCEtLSAgIHVuZ3JvdXAoKSAlPiUgIC0tPgo8IS0tICAgbXV0YXRlKGdlbm90eXBlciA9IHJlZm9ybWF0X2hsYV9nZW5vdHlwZXIoZ2Vub3R5cGVyKSkgJT4lICAtLT4KPCEtLSAgIGdncGxvdChhZXMoeCA9IGdlbm90eXBlciwgeSA9IFRFLCB5bWluID0gbG93ZXIsIHltYXggPSB1cHBlciwgZmlsbCA9IGdyb3VwKSkrIC0tPgo8IS0tICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC4yNSkrIC0tPgo8IS0tICAgZ2VvbV9lcnJvcmJhcihwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuOSksIHdpZHRoID0wLjUpKyAtLT4KPCEtLSAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEsIGxpbmV0eXBlID0gImRhc2hlZCIpKyAtLT4KPCEtLSAgIHRoZW1lX2J3KCkrIC0tPgo8IS0tICAgZmFjZXRfd3JhcCh+Z3JvdXAsIG5jb2wgPSA0KSsgLS0+CjwhLS0gICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArIC0tPgo8IS0tICAgbGFicyh5ID0gIk9kZHMgcmF0aW8gb2YgZG9taW5hbnQgYWxsZWxlIiwgeD0gTlVMTCkgKyAtLT4KPCEtLSAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSAtLT4KCjwhLS0geSAlPiUgIC0tPgo8IS0tICAgdW5ncm91cCgpICU+JSAgLS0+CjwhLS0gICBtdXRhdGUoZ2Vub3R5cGVyID0gcmVmb3JtYXRfaGxhX2dlbm90eXBlcihnZW5vdHlwZXIpKSAlPiUgIC0tPgo8IS0tICAgZ2dwbG90KGFlcyh4ID0gZ3JvdXAsIHkgPSBURSwgeW1pbiA9IGxvd2VyLCB5bWF4ID0gdXBwZXIsIGZpbGwgPSBjZWxsdHlwZSkpKyAtLT4KPCEtLSAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDAuMjUpKyAtLT4KPCEtLSAgIGdlb21fZXJyb3JiYXIocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpLCB3aWR0aCA9MC41KSsgLS0+CjwhLS0gICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSsgLS0+CjwhLS0gICB0aGVtZV9idygpKyAtLT4KPCEtLSAgIGZhY2V0X2dyaWQoZ2VuZX5nZW5vdHlwZXIsIHNjYWxlcyA9ICJmcmVlX3kiKSsgLS0+CjwhLS0gICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArIC0tPgo8IS0tICAgbGFicyh5ID0gIk9kZHMgcmF0aW8gb2YgZG9taW5hbnQgYWxsZWxlIiwgeD0gTlVMTCkgKyAtLT4KPCEtLSAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSAtLT4KCjwhLS0geSAlPiUgIC0tPgo8IS0tICAgdW5ncm91cCgpICU+JSAgLS0+CjwhLS0gICBmaWx0ZXIoZ3JvdXAgPT0gInBEQyIpICU+JSAgLS0+CjwhLS0gICBtdXRhdGUoZ2Vub3R5cGVyID0gcmVmb3JtYXRfaGxhX2dlbm90eXBlcihnZW5vdHlwZXIpKSAlPiUgIC0tPgo8IS0tICAgZ2dwbG90KGFlcyh4ID0gZ2Vub3R5cGVyLCB5ID0gVEUsIHltaW4gPSBsb3dlciwgeW1heCA9IHVwcGVyKSkrIC0tPgo8IS0tICAgZ2VvbV9wb2ludCgpKyAtLT4KPCEtLSAgIGdlb21fZXJyb3JiYXIoKSsgLS0+CjwhLS0gICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSsgLS0+CjwhLS0gICB0aGVtZV9idygpKyAtLT4KPCEtLSAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsgLS0+CjwhLS0gICBsYWJzKHkgPSAiT2RkcyByYXRpbyBvZiBkb21pbmFudCBhbGxlbGUiLCB4PSBOVUxMKSAtLT4KPCEtLSBgYGAgLS0+CgoKCgo8IS0tICMgQXNzZW1ibGUgcGxvdCAtLT4KPCEtLSBgYGB7ciwgZmlnLndpZHRoID0gMTQsIGZpZy5oZWlnaHQgPSA2fSAtLT4KPCEtLSAjIHBsdF9hbGxlbGVfZnJlcV9sZ2QgPC0gY293cGxvdDo6Z2V0X2xlZ2VuZChwbHRfYWxsZWxlX2ZyZXEpIC0tPgo8IS0tICMgcGx0X21heF9hbGxlbGVfbGdkIDwtIGNvd3Bsb3Q6OmdldF9sZWdlbmQocGx0X21heF9hbGxlbGUpIC0tPgo8IS0tIGNvbF8xIDwtIHBsb3RfZ3JpZCggLS0+CjwhLS0gICBwbHRfYWxsZWxlX2ZyZXEsIC0tPgo8IS0tICAgcGx0X21heF9hbGxlbGUsIC0tPgo8IS0tICAgbmNvbCA9IDEsIC0tPgo8IS0tICAgcmVsX2hlaWdodHMgPSBjKDUsMyksIC0tPgo8IS0tICAgYWxpZ24gPSAidiIsIGF4aXMgPSAibHIiLCAtLT4KPCEtLSAgIGxhYmVscyA9IExFVFRFUlNbMToyXSAtLT4KPCEtLSApIC0tPgoKPCEtLSBjb2xfMiA8LSBwbG90X2dyaWQoIC0tPgo8IS0tICAgcGx0X3NydCwgLS0+CjwhLS0gICBwbHRfbWV0YSwgLS0+CjwhLS0gICBuY29sID0gMSwgLS0+CjwhLS0gICBhbGlnbiA9ICJ2IiwgYXhpcyA9ICJsciIsIC0tPgo8IS0tICAgbGFiZWxzID0gTEVUVEVSU1szOjRdLCAtLT4KPCEtLSAgIGhqdXN0ID0gMC41IC0tPgo8IS0tICkgLS0+CjwhLS0gcGxvdF9ncmlkKCAtLT4KPCEtLSAgIGNvbF8xLCAtLT4KPCEtLSAgIGNvbF8yLCAgLS0+CjwhLS0gICBucm93ID0gMSwgLS0+CjwhLS0gICByZWxfd2lkdGhzID0gYyg2LDMpIC0tPgo8IS0tICkgLS0+CjwhLS0gYGBgIC0tPgoKCgoKCgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gZyA8LSBnZ3Bsb3RfYnVpbGQocGx0X3NydCkgLS0+Cgo8IS0tIHBsdF9pZHMgPC0gZyRkYXRhW1sxXV0gLS0+CjwhLS0gZ3JvdXBfbGV2ZWxzIDwtIGxldmVscyhmYWN0b3IoZyRwbG90JGRhdGFbW2ckcGxvdCRsYWJlbHMkY29sb3VyXV0pKSAtLT4KCjwhLS0gcGx0X2tleSA8LSBnJGRhdGFbWzFdXSAlPiUgIC0tPgo8IS0tICAgc2VsZWN0KGNvbG91ciwgZ3JvdXApICU+JSAgLS0+CjwhLS0gICBkaXN0aW5jdCgpICU+JSAgLS0+CjwhLS0gICBtdXRhdGUobGFiZWwgPSBtYXBfY2hyKGdyb3VwLCBmdW5jdGlvbih4KSBncm91cF9sZXZlbHNbeF0pKSAlPiUgIC0tPgo8IS0tICAgbXV0YXRlKGxhYmVsID0gZmFjdG9yKGxhYmVsLCBsZXZlbCA9IGdyb3VwX2xldmVscykpICU+JSAtLT4KPCEtLSAgIG11dGF0ZShsYWJlbCA9IHNwcmludGYoIiVzKSAlcyIsIDE6bigpLCBsYWJlbCkpICU+JSAgLS0+CjwhLS0gICBzZWxlY3QoLWdyb3VwKSAtLT4KCjwhLS0gICAjIGxldmVscyhmYWN0b3IoZyRwbG90JGRhdGFbW2ckcGxvdCRsYWJlbHMkY29sb3VyXV0pKSAtLT4KPCEtLSAgICMgZGF0YS5mcmFtZShjb2xvdXJzID0gdW5pcXVlKGckZGF0YVtbMV1dWyJjb2xvdXIiXSksICAtLT4KPCEtLSAgICMgICAgICAgICAgICAgIGxhYmVsID0gbGV2ZWxzKGZhY3RvcihnJHBsb3QkZGF0YVtbZyRwbG90JGxhYmVscyRjb2xvdXJdXSkpKSAlPiUgIC0tPgoKPCEtLSBwbHRfZGYgPC0gcGx0X2lkcyAlPiUgIC0tPgo8IS0tICAgbGVmdF9qb2luKHBsdF9rZXksIGJ5ID0gImNvbG91ciIpIC0tPgoKPCEtLSBwbHRfY2VudGVyIDwtIHBsdF9kZiAlPiUgIC0tPgo8IS0tICAgZ3JvdXBfYnkobGFiZWwpICU+JSBzdW1tYXJpc2UoeCA9IG1lYW4oeCksIHkgPSBtZWFuKHkpKSAlPiUgLS0+CjwhLS0gICBtdXRhdGUobGFiZWwgPSBnc3ViKCIpLioiLCIiLGxhYmVsKSkgLS0+Cgo8IS0tIHBsdF9yZXBlbCA8LSBwbHRfZGYgJT4lICAtLT4KPCEtLSAgIGdncGxvdChhZXMoeD14LHk9eSxjb2xvcj1sYWJlbCkpICsgLS0+CjwhLS0gICBnZW9tX3BvaW50KHNpemUgPSAwLjUpKyAtLT4KPCEtLSAgICMgZ2VvbV9wb2ludChkYXRhID0gcGx0X2NlbnRlciwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMikgLS0+CjwhLS0gICBnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoZGF0YT1wbHRfY2VudGVyLGFlcyhsYWJlbD1sYWJlbCwgIGJnLmNvbG9yPSJ3aGl0ZSIsIGJnLnI9MC4yNSxtaW4uc2VnbWVudC5sZW5ndGggPSAwKSxjb2xvciA9ICJibGFjayIsZm9udGZhY2UgPSAiYm9sZCIpICsgLS0+CjwhLS0gICB0aGVtZV9idygpICsgLS0+CjwhLS0gICBndWlkZXMoY29sb3IgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaXplID0gMikgKSApICsgLS0+CjwhLS0gICBsYWJzKHg9IlVNQVAgMSIsIHkgPSAiVU1BUCAyIiwgY29sb3IgPSAiQ2VsbCBDbHVzdGVyIikgKyAtLT4KPCEtLSAgIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikrICAtLT4KPCEtLSAgIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSkgLS0+CjwhLS0gcGx0X3JlcGVsIC0tPgoKPCEtLSBgYGAgLS0+CgoKCgoKCg==